diff --git a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryClient.java b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryClient.java index 59215dc81fe79..221ece8ae3b74 100644 --- a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryClient.java +++ b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryClient.java @@ -50,6 +50,7 @@ public class BigQueryClient private final Optional viewMaterializationProject; private final Optional viewMaterializationDataset; private final String tablePrefix = "_pbc_"; + private final boolean caseSensitiveNameMatching; // presto converts the dataset and table names to lower case, while BigQuery is case sensitive private final ConcurrentMap tableIds = new ConcurrentHashMap<>(); @@ -60,6 +61,7 @@ public class BigQueryClient this.bigQuery = requireNonNull(bigQuery, "bigQuery is null"); this.viewMaterializationProject = requireNonNull(config.getViewMaterializationProject(), "viewMaterializationProject is null"); this.viewMaterializationDataset = requireNonNull(config.getViewMaterializationDataset(), "viewMaterializationDataset is null"); + this.caseSensitiveNameMatching = config.isCaseSensitiveNameMatching(); } public TableInfo getTable(TableId tableId) @@ -108,7 +110,7 @@ private void addTableMappingIfNeeded(DatasetId datasetID, Table table) private Dataset addDataSetMappingIfNeeded(Dataset dataset) { DatasetId bigQueryDatasetId = dataset.getDatasetId(); - DatasetId prestoDatasetId = DatasetId.of(bigQueryDatasetId.getProject(), bigQueryDatasetId.getDataset().toLowerCase(ENGLISH)); + DatasetId prestoDatasetId = DatasetId.of(bigQueryDatasetId.getProject(), bigQueryDatasetId.getDataset()); datasetIds.putIfAbsent(prestoDatasetId, bigQueryDatasetId); return dataset; } @@ -123,7 +125,8 @@ protected TableId createDestinationTable(TableId tableId) private String createTableName() { - return format(tablePrefix + "%s", randomUUID().toString().toLowerCase(ENGLISH).replace("-", "")); + String uuid = randomUUID().toString().replace("-", ""); + return caseSensitiveNameMatching ? format("%s%s", tablePrefix, uuid) : format("%s%s", tablePrefix, uuid).toLowerCase(ENGLISH); } private DatasetId mapIfNeeded(String project, String dataset) diff --git a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryConfig.java b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryConfig.java index 86e09dba9077e..1247f385e1514 100644 --- a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryConfig.java +++ b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryConfig.java @@ -35,6 +35,7 @@ public class BigQueryConfig private Optional parentProjectId = Optional.empty(); private OptionalInt parallelism = OptionalInt.empty(); private boolean viewsEnabled; + private boolean caseSensitiveNameMatching; private Optional viewMaterializationProject = Optional.empty(); private Optional viewMaterializationDataset = Optional.empty(); private int maxReadRowsRetries = DEFAULT_MAX_READ_ROWS_RETRIES; @@ -181,6 +182,22 @@ public BigQueryConfig setMaxReadRowsRetries(int maxReadRowsRetries) return this; } + public boolean isCaseSensitiveNameMatching() + { + return caseSensitiveNameMatching; + } + + @Config("case-sensitive-name-matching") + @ConfigDescription( + "Case sensitivity for schema and table name matching. " + + "true = preserve case and require exact matches; " + + "false (default) = normalize to lower case and match case-insensitively.") + public BigQueryConfig setCaseSensitiveNameMatching(boolean caseSensitiveNameMatching) + { + this.caseSensitiveNameMatching = caseSensitiveNameMatching; + return this; + } + ReadSessionCreatorConfig createReadSessionCreatorConfig() { return new ReadSessionCreatorConfig( diff --git a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryMetadata.java b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryMetadata.java index 8c028fbf59b7f..ad0bf4775a42b 100644 --- a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryMetadata.java +++ b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryMetadata.java @@ -51,6 +51,7 @@ import static com.google.cloud.bigquery.TableDefinition.Type.TABLE; import static com.google.cloud.bigquery.TableDefinition.Type.VIEW; import static com.google.common.collect.ImmutableList.toImmutableList; +import static java.util.Locale.ENGLISH; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toMap; @@ -63,12 +64,14 @@ public class BigQueryMetadata private static final Logger log = Logger.get(BigQueryMetadata.class); private final BigQueryClient bigQueryClient; private final String projectId; + private final boolean caseSensitiveNameMatching; @Inject public BigQueryMetadata(BigQueryClient bigQueryClient, BigQueryConfig config) { this.bigQueryClient = bigQueryClient; this.projectId = config.getProjectId().orElse(bigQueryClient.getProjectId()); + this.caseSensitiveNameMatching = config.isCaseSensitiveNameMatching(); } @Override @@ -233,4 +236,10 @@ private List listTables(ConnectorSession session, SchemaTablePr ImmutableList.of(tableName) : ImmutableList.of(); // table does not exist } + + @Override + public String normalizeIdentifier(ConnectorSession session, String identifier) + { + return caseSensitiveNameMatching ? identifier : identifier.toLowerCase(ENGLISH); + } } diff --git a/presto-bigquery/src/test/java/com/facebook/presto/plugin/bigquery/TestBigQueryConfig.java b/presto-bigquery/src/test/java/com/facebook/presto/plugin/bigquery/TestBigQueryConfig.java index 053f83600eb85..8829d86cd6e23 100644 --- a/presto-bigquery/src/test/java/com/facebook/presto/plugin/bigquery/TestBigQueryConfig.java +++ b/presto-bigquery/src/test/java/com/facebook/presto/plugin/bigquery/TestBigQueryConfig.java @@ -36,7 +36,8 @@ public void testDefaults() .setParallelism(20) .setViewMaterializationProject("vmproject") .setViewMaterializationDataset("vmdataset") - .setMaxReadRowsRetries(10); + .setMaxReadRowsRetries(10) + .setCaseSensitiveNameMatching(false); assertEquals(config.getCredentialsKey(), Optional.of("ckey")); assertEquals(config.getCredentialsFile(), Optional.of("cfile")); @@ -46,6 +47,7 @@ public void testDefaults() assertEquals(config.getViewMaterializationProject(), Optional.of("vmproject")); assertEquals(config.getViewMaterializationDataset(), Optional.of("vmdataset")); assertEquals(config.getMaxReadRowsRetries(), 10); + assertEquals(config.isCaseSensitiveNameMatching(), false); } @Test @@ -59,6 +61,7 @@ public void testExplicitPropertyMappingsWithCredentialsKey() .put("bigquery.view-materialization-project", "vmproject") .put("bigquery.view-materialization-dataset", "vmdataset") .put("bigquery.max-read-rows-retries", "10") + .put("case-sensitive-name-matching", "true") .build(); ConfigurationFactory configurationFactory = new ConfigurationFactory(properties); @@ -71,6 +74,7 @@ public void testExplicitPropertyMappingsWithCredentialsKey() assertEquals(config.getViewMaterializationProject(), Optional.of("vmproject")); assertEquals(config.getViewMaterializationDataset(), Optional.of("vmdataset")); assertEquals(config.getMaxReadRowsRetries(), 10); + assertEquals(config.isCaseSensitiveNameMatching(), true); } @Test diff --git a/presto-docs/src/main/sphinx/connector/bigquery.rst b/presto-docs/src/main/sphinx/connector/bigquery.rst index d71c600b758c8..4e90e92555da0 100644 --- a/presto-docs/src/main/sphinx/connector/bigquery.rst +++ b/presto-docs/src/main/sphinx/connector/bigquery.rst @@ -137,6 +137,9 @@ Property Description ``bigquery.max-read-rows-retries`` The number of retries in case of retryable server issues ``3`` ``bigquery.credentials-key`` credentials key (base64 encoded) None. See `authentication <#authentication>`_ ``bigquery.credentials-file`` JSON credentials file path None. See `authentication <#authentication>`_ +``case-sensitive-name-matching`` Enable case sensitive identifier support for schema and table ``false`` + names for the connector. When disabled, names are matched + case-insensitively using lowercase normalization. ========================================= ============================================================== ============================================== Data Types