klsince commented on code in PR #12417: URL: https://github.com/apache/pinot/pull/12417#discussion_r1503447394
########## pinot-common/src/main/java/org/apache/pinot/common/utils/DatabaseUtils.java: ########## @@ -0,0 +1,90 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.pinot.common.utils; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nullable; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.core.MultivaluedMap; +import org.apache.pinot.common.config.provider.TableCache; +import org.apache.pinot.spi.utils.CommonConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class DatabaseUtils { + private DatabaseUtils() { + } + + private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseUtils.class); + + private static final List<String> TABLE_NAME_KEYS = List.of("tableName", "tableNameWithType", "schemaName"); + + public static void translateTableNameQueryParam(ContainerRequestContext requestContext, TableCache tableCache) { + MultivaluedMap<String, String> queryParams = requestContext.getUriInfo().getQueryParameters(); + String uri = requestContext.getUriInfo().getRequestUri().toString(); + String databaseName = null; + if (requestContext.getHeaders().containsKey(CommonConstants.DATABASE)) { + databaseName = requestContext.getHeaderString(CommonConstants.DATABASE); + } + for (String key : TABLE_NAME_KEYS) { + if (queryParams.containsKey(key)) { + String tableName = queryParams.getFirst(key); + String actualTableName = translateTableName(tableName, databaseName, tableCache); + // table is not part of default database + if (!actualTableName.equals(tableName)) { + uri = uri.replaceAll(String.format("%s=%s", key, tableName), + String.format("%s=%s", key, actualTableName)); + try { + requestContext.setRequestUri(new URI(uri)); Review Comment: call this setRequestUri after finishing the for-loop? ########## pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/BaseBrokerRequestHandler.java: ########## @@ -1660,10 +1640,25 @@ static String getActualColumnName(String rawTableName, String columnName, @Nulla return columnName; } String columnNameToCheck; - if (columnName.regionMatches(ignoreCase, 0, rawTableName, 0, rawTableName.length()) - && columnName.length() > rawTableName.length() && columnName.charAt(rawTableName.length()) == '.') { - columnNameToCheck = ignoreCase ? columnName.substring(rawTableName.length() + 1).toLowerCase() - : columnName.substring(rawTableName.length() + 1); + String resolvedColumnName = columnName; + if (rawTableName.contains(".")) { // table name has database prefix + String databaseName = rawTableName.split("\\.")[0]; Review Comment: What if database, table or column name has '.' in its name? or is it allowed to have '.'. I think currently there is no sanity check to block this. The previous logic above used the name.length() to split. ########## pinot-common/src/main/java/org/apache/pinot/common/utils/DatabaseUtils.java: ########## @@ -0,0 +1,90 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.pinot.common.utils; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nullable; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.core.MultivaluedMap; +import org.apache.pinot.common.config.provider.TableCache; +import org.apache.pinot.spi.utils.CommonConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class DatabaseUtils { + private DatabaseUtils() { + } + + private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseUtils.class); + + private static final List<String> TABLE_NAME_KEYS = List.of("tableName", "tableNameWithType", "schemaName"); + + public static void translateTableNameQueryParam(ContainerRequestContext requestContext, TableCache tableCache) { + MultivaluedMap<String, String> queryParams = requestContext.getUriInfo().getQueryParameters(); + String uri = requestContext.getUriInfo().getRequestUri().toString(); + String databaseName = null; + if (requestContext.getHeaders().containsKey(CommonConstants.DATABASE)) { + databaseName = requestContext.getHeaderString(CommonConstants.DATABASE); + } + for (String key : TABLE_NAME_KEYS) { + if (queryParams.containsKey(key)) { + String tableName = queryParams.getFirst(key); + String actualTableName = translateTableName(tableName, databaseName, tableCache); + // table is not part of default database + if (!actualTableName.equals(tableName)) { + uri = uri.replaceAll(String.format("%s=%s", key, tableName), + String.format("%s=%s", key, actualTableName)); + try { + requestContext.setRequestUri(new URI(uri)); + } catch (URISyntaxException e) { + LOGGER.error("Unable to translate the table name from {} to {}", tableName, actualTableName); + } + } + } + } + } + + public static String translateTableName(String tableName, String databaseName, @Nullable TableCache tableCache) { + if (tableName != null && databaseName != null) { + String[] tableSplit = tableName.split("\\."); + if (tableSplit.length > 2) { + throw new IllegalStateException("Table name: '" + tableName + "' containing more than one '.' is not allowed"); + } else if (tableSplit.length == 2) { + databaseName = tableSplit[0]; + tableName = tableSplit[1]; + } + if (databaseName != null && !databaseName.isBlank()) { + tableName = String.format("%s.%s", databaseName, tableName); + } + } + String actualTableName = null; + if (tableCache != null) { + actualTableName = tableCache.getActualTableName(tableName); + } + return actualTableName != null ? actualTableName : tableName; + } + + public static boolean isTableNameEquivalent(String name1, String name2) { + return Objects.equals(name1, name2) || name1.endsWith("." + name2) || name2.endsWith("." + name1); + } Review Comment: looks like the logic heavily assumes the names don't contain `.`, but would this assumption be held true? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org