blob: cdd7dd9b44eb513be0e547e91cc18bd8cb62dd4c [file] [log] [blame]
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License"),
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.ericsson.gerrit.plugins.gcconductor.postgresqueue;
import static java.lang.String.format;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Optional;
import org.apache.commons.dbcp.BasicDataSource;
final class DatabaseConstants {
static final String DRIVER = "org.postgresql.Driver";
static final String INITIAL_DATABASE = "postgres";
private static final String REPOSITORIES_TABLE = "repositories";
static final String REPOSITORY = "repository";
static final String EXECUTOR = "executor";
private static final String SEQUENCE = "sequence";
static final String QUEUED_AT = "queued_at";
static final String HOSTNAME = "hostname";
static final String AGGRESSIVE = "aggressive";
static final String CREATE_OR_UPDATE_SCHEMA =
"DO"
+ " $$"
+ " BEGIN"
+ " CREATE TABLE IF NOT EXISTS "
+ REPOSITORIES_TABLE
+ "("
+ REPOSITORY
+ " VARCHAR(4096) PRIMARY KEY, "
+ SEQUENCE
+ " BIGSERIAL UNIQUE, "
+ QUEUED_AT
+ " TIMESTAMP WITHOUT TIME ZONE DEFAULT localtimestamp, "
+ EXECUTOR
+ " VARCHAR(258), "
+ HOSTNAME
+ " VARCHAR(255) NOT NULL, "
+ AGGRESSIVE
+ " BOOLEAN NOT NULL"
+ ");"
// This section is temporary to support migrating live, next version will
// drop the executor tables, only drop the foreign key for now.
+ " IF EXISTS ("
+ " SELECT constraint_name FROM information_schema.table_constraints"
+ " WHERE table_name='"
+ REPOSITORIES_TABLE
+ "'"
+ " AND constraint_name='repositories_executor_fkey')"
+ " THEN"
+ " ALTER TABLE "
+ REPOSITORIES_TABLE
+ " DROP CONSTRAINT repositories_executor_fkey;"
+ " END IF;"
+ " BEGIN ALTER TABLE "
+ REPOSITORIES_TABLE
+ " ADD COLUMN "
+ AGGRESSIVE
+ " BOOLEAN NOT NULL DEFAULT (true);"
+ " EXCEPTION WHEN duplicate_column THEN RAISE NOTICE 'column "
+ AGGRESSIVE
+ " already exists in "
+ REPOSITORIES_TABLE
+ ".';"
+ " END;"
+ " END "
+ " $$";
private static final String SELECT_REPOSITORIES = "SELECT * FROM " + REPOSITORIES_TABLE;
static final String SELECT_REPOSITORIES_ORDERED = SELECT_REPOSITORIES + " ORDER BY " + SEQUENCE;
private DatabaseConstants() {}
static final String databaseExists(String name) {
return "SELECT 1 from pg_database WHERE datname='" + name + "'";
}
static final String createDatabase(String name) {
return "CREATE DATABASE " + name;
}
static final String dropDatabase(String name) {
return "DROP DATABASE " + name;
}
static final String select(String repository) {
return SELECT_REPOSITORIES + " WHERE " + REPOSITORY + "='" + repository + "'";
}
static final String insert(String repository, String hostname, boolean isAggressive) {
return format(
"INSERT INTO %s (%s,%s,%s) SELECT '%s','%s','%b' WHERE NOT EXISTS (%s)",
REPOSITORIES_TABLE,
REPOSITORY,
HOSTNAME,
AGGRESSIVE,
repository,
hostname,
isAggressive,
select(repository));
}
static final String delete(String repository) {
return "DELETE FROM " + REPOSITORIES_TABLE + " WHERE " + REPOSITORY + "='" + repository + "'";
}
static final String updateExecutor(
String executor, long queuedForLongerThan, Optional<String> queuedFrom) {
return format(
"UPDATE %s SET %s='%s' WHERE %s IN (SELECT %s FROM %s WHERE (%s is null OR %s='' OR %s='%s') AND age(localtimestamp, queued_at) > '%s' %s ORDER BY %s LIMIT 1 FOR UPDATE OF %s) RETURNING *",
REPOSITORIES_TABLE,
EXECUTOR,
executor,
REPOSITORY,
REPOSITORY,
REPOSITORIES_TABLE,
EXECUTOR,
EXECUTOR,
EXECUTOR,
executor,
queuedForLongerThan,
(queuedFrom.isPresent() ? " AND '" + queuedFrom.get() + "' LIKE hostname||'%'" : ""),
SEQUENCE,
REPOSITORIES_TABLE);
}
static final String updateQueuedFrom(String hostname) {
return format(
"UPDATE %s SET %s='%s' WHERE %s is NULL", REPOSITORIES_TABLE, HOSTNAME, hostname, EXECUTOR);
}
static final String clearExecutor(String repository) {
return format(
"UPDATE %s SET %s=NULL WHERE %s='%s'",
REPOSITORIES_TABLE, EXECUTOR, REPOSITORY, repository);
}
static final String bumpRepository(String repository) {
return format(
"UPDATE %s SET %s=(SELECT min(%s) FROM %s) -1 WHERE %s='%s'",
REPOSITORIES_TABLE, SEQUENCE, SEQUENCE, REPOSITORIES_TABLE, REPOSITORY, repository);
}
static boolean executeStatement(BasicDataSource ds, String query) throws SQLException {
try (Connection conn = ds.getConnection();
Statement stat = conn.createStatement()) {
return stat.execute(query);
}
}
}