Skip to content

Commit

Permalink
fix: support information_schema.sequences
Browse files Browse the repository at this point in the history
Adds support for information_schema.sequences using a common table
expression. The CTE always returns zero rows and is there purely for
compatibility reasons.

Towards #705
  • Loading branch information
olavloite committed Mar 3, 2023
1 parent b2c1f1e commit e1cf0cf
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
Expand Down Expand Up @@ -66,6 +67,9 @@ public class PgCatalog {
.put(
new TableOrIndexName(null, "pg_sequences"),
new TableOrIndexName(null, "pg_sequences"))
.put(
new TableOrIndexName("information_schema", "sequences"),
new TableOrIndexName(null, "pg_information_schema_sequences"))
.put(
new TableOrIndexName("pg_catalog", "pg_settings"),
new TableOrIndexName(null, "pg_settings"))
Expand Down Expand Up @@ -95,7 +99,9 @@ public class PgCatalog {
new TableOrIndexName(null, "pg_range"), new PgRange(),
new TableOrIndexName(null, "pg_type"), new PgType(),
new TableOrIndexName(null, "pg_sequence"), new PgSequence(),
new TableOrIndexName(null, "pg_sequences"), new PgSequences());
new TableOrIndexName(null, "pg_sequences"), new PgSequences(),
new TableOrIndexName(null, "pg_information_schema_sequences"),
new InformationSchemaSequences());
private final SessionState sessionState;

public PgCatalog(@Nonnull SessionState sessionState, @Nonnull WellKnownClient wellKnownClient) {
Expand Down Expand Up @@ -130,7 +136,8 @@ public PgCatalog(@Nonnull SessionState sessionState, @Nonnull WellKnownClient we
/** Replace supported pg_catalog tables with Common Table Expressions. */
public Statement replacePgCatalogTables(Statement statement) {
// Only replace tables if the statement contains at least one of the known prefixes.
if (checkPrefixes.stream().noneMatch(prefix -> statement.getSql().contains(prefix))) {
String sql = statement.getSql().toLowerCase(Locale.ENGLISH);
if (checkPrefixes.stream().noneMatch(sql::contains)) {
return statement;
}

Expand Down Expand Up @@ -514,4 +521,22 @@ public String getTableExpression() {
return PG_SEQUENCE_CTE;
}
}

private static class InformationSchemaSequences implements PgCatalogTable {
// The name of this CTE is a little strange, but that is to make sure it does not accidentally
// collide with any user-defined table or view.
private static final String INFORMATION_SCHEMA_SEQUENCES_CTE =
"pg_information_schema_sequences as (\n"
+ "select * from ("
+ "select ''::varchar as sequence_catalog, ''::varchar as sequence_schema, ''::varchar as sequence_name, "
+ "''::varchar as data_type, 0::bigint as numeric_precision, 0::bigint as numeric_precision_radix, "
+ "''::varchar as start_value, ''::varchar as minimum_value, ''::varchar as maximum_value, "
+ "''::varchar as increment, 'NO'::varchar as cycle_option\n"
+ ") seq where false)";

@Override
public String getTableExpression() {
return INFORMATION_SCHEMA_SEQUENCES_CTE;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class ClientAutoDetector {
SelectVersionStatement.INSTANCE,
DjangoGetTableNamesStatement.INSTANCE);
private static final ImmutableSet<String> DEFAULT_CHECK_PG_CATALOG_PREFIXES =
ImmutableSet.of("pg_");
ImmutableSet.of("pg_", "information_schema.");
public static final String PGBENCH_USAGE_HINT =
"See https://github.com/GoogleCloudPlatform/pgadapter/blob/-/docs/pgbench.md for how to use pgbench with PGAdapter";

Expand Down
15 changes: 15 additions & 0 deletions src/test/java/com/google/cloud/spanner/pgadapter/ITJdbcTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,21 @@ public void testPgCatalogViews() throws SQLException {
}
}

@Test
public void testInformationSchemaViews() throws SQLException {
for (String view : new String[] {"sequences"}) {
try (Connection connection = DriverManager.getConnection(getConnectionUrl())) {
try (ResultSet resultSet =
connection.createStatement().executeQuery("SELECT * FROM INFORMATION_SCHEMA." + view)) {
while (resultSet.next()) {
assertNotNull(resultSet.getMetaData());
assertNotEquals(0, resultSet.getMetaData().getColumnCount());
}
}
}
}
}

@Test
public void testCreateTableIfNotExists() throws SQLException {
try (Connection connection = DriverManager.getConnection(getConnectionUrl())) {
Expand Down

0 comments on commit e1cf0cf

Please sign in to comment.