This is an automated email from the ASF dual-hosted git repository.
richardantal pushed a commit to branch 4.x
in repository https://gitbox.apache.org/repos/asf/phoenix.git
The following commit(s) were added to refs/heads/4.x by this push:
new 6e8fe10 PHOENIX-6519 Make SchemaTool work with lower case table and
column names
6e8fe10 is described below
commit 6e8fe10bfa30845901b040eaa39b6b48bd8a3951
Author: Richard Antal <[email protected]>
AuthorDate: Mon Jul 26 16:34:44 2021 +0200
PHOENIX-6519 Make SchemaTool work with lower case table and column names
Change-Id: I643ed8c3db1ec7ebd0a68b13412a22ff7249f037
---
.../apache/phoenix/end2end/ShowCreateTableIT.java | 1 -
.../schema/tool/SchemaToolExtractionIT.java | 72 +++++++++++++++++++++
.../schema/tool/SchemaExtractionProcessor.java | 62 +++++++++++-------
.../java/org/apache/phoenix/util/SchemaUtil.java | 73 ++++++++++++++++++++++
4 files changed, 183 insertions(+), 25 deletions(-)
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ShowCreateTableIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ShowCreateTableIT.java
index f4502d0..4895a84 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ShowCreateTableIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ShowCreateTableIT.java
@@ -43,7 +43,6 @@ public class ShowCreateTableIT extends
ParallelStatsDisabledIT {
rs.getString(1).contains(ddl));
}
- @Ignore
@Test
public void testShowCreateTableLowerCase() throws Exception {
Properties props = new Properties();
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/schema/tool/SchemaToolExtractionIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/schema/tool/SchemaToolExtractionIT.java
index 89bd53a..0fd1603 100644
---
a/phoenix-core/src/it/java/org/apache/phoenix/schema/tool/SchemaToolExtractionIT.java
+++
b/phoenix-core/src/it/java/org/apache/phoenix/schema/tool/SchemaToolExtractionIT.java
@@ -71,6 +71,19 @@ public class SchemaToolExtractionIT extends
ParallelStatsEnabledIT {
}
@Test
+ public void testCreateTableStatementLowerCase() throws Exception {
+ String tableName = "lowecasetbl1";
+ String schemaName = "lowecaseschemaname1";
+ String pTableFullName = SchemaUtil.getEscapedTableName(schemaName,
tableName);
+ String createTableStmt = "CREATE TABLE "+ pTableFullName +
"(\"smallK\" VARCHAR NOT NULL PRIMARY KEY, "
+ + "\"asd\".V1 VARCHAR, \"foo\".\"bar\" VARCHAR) TTL=2592000,
IMMUTABLE_ROWS=true, DISABLE_WAL=true";
+ List<String> queries = new ArrayList<String>(){};
+ queries.add(createTableStmt);
+ String result = runSchemaExtractionTool("\"" + schemaName + "\"", "\""
+ tableName + "\"", null, queries);
+ Assert.assertEquals(createTableStmt, result);
+ }
+
+ @Test
public void testCreateIndexStatement() throws Exception {
String tableName = generateUniqueName();
String schemaName = generateUniqueName();
@@ -124,6 +137,42 @@ public class SchemaToolExtractionIT extends
ParallelStatsEnabledIT {
}
@Test
+ public void testCreateLocalIndexStatement() throws Exception {
+ String tableName = generateUniqueName();
+ String schemaName = generateUniqueName();
+ String indexName = generateUniqueName();
+ String properties = "TTL=2592000,IMMUTABLE_ROWS=true,DISABLE_WAL=true";
+ String pTableFullName = SchemaUtil.getQualifiedTableName(schemaName,
tableName);
+ String createTableStatement = "CREATE TABLE "+pTableFullName + "(k
VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR)"
+ + properties;
+ String createIndexStatement = "CREATE LOCAL INDEX "+indexName + " ON
"+pTableFullName+"(v1 DESC, k) INCLUDE (v2)";
+ List<String> queries = new ArrayList<String>(){};
+ queries.add(createTableStatement);
+ queries.add(createIndexStatement);
+
+ String result = runSchemaExtractionTool(schemaName, indexName, null,
queries);
+ Assert.assertEquals(createIndexStatement.toUpperCase(),
result.toUpperCase());
+ }
+
+ @Test
+ public void testCreateIndexStatementLowerCase() throws Exception {
+ String tableName = "lowercase" + generateUniqueName();
+ String schemaName = "lowercase" + generateUniqueName();
+ String indexName = "\"lowercaseIND" + generateUniqueName() + "\"";
+ String properties = "TTL=2592000,IMMUTABLE_ROWS=true,DISABLE_WAL=true";
+ String pTableFullName = SchemaUtil.getEscapedTableName(schemaName,
tableName);
+ String createTableStatement = "CREATE TABLE " + pTableFullName +
"(\"k\" VARCHAR NOT NULL PRIMARY KEY, \"a\".V1 VARCHAR, \"v2\" VARCHAR)"
+ + properties;
+ String createIndexStatement = "CREATE INDEX " + indexName + " ON "+
pTableFullName + "(\"a\".V1 DESC, \"k\") INCLUDE (\"v2\")";
+ List<String> queries = new ArrayList<String>(){};
+ queries.add(createTableStatement);
+ queries.add(createIndexStatement);
+
+ String result = runSchemaExtractionTool("\"" + schemaName + "\"",
indexName, null, queries);
+ Assert.assertEquals(createIndexStatement, result);
+ }
+
+ @Test
public void testCreateViewStatement() throws Exception {
String tableName = generateUniqueName();
String schemaName = generateUniqueName();
@@ -148,6 +197,29 @@ public class SchemaToolExtractionIT extends
ParallelStatsEnabledIT {
}
@Test
+ public void testCreateViewStatementLowerCase() throws Exception {
+ String tableName = "lowercase" + generateUniqueName();
+ String schemaName = "lowercase" + generateUniqueName();
+ String viewName = "lowercase" + generateUniqueName();
+ String properties = "TTL=2592000,IMMUTABLE_ROWS=true,DISABLE_WAL=true";
+
+ String pTableFullName = SchemaUtil.getEscapedTableName(schemaName,
tableName);
+ String createTableStmt = "CREATE TABLE "+pTableFullName + "(\"k\"
BIGINT NOT NULL PRIMARY KEY, "
+ + "\"a\".V1 VARCHAR, v2 VARCHAR)"
+ + properties;
+ String viewFullName = SchemaUtil.getEscapedTableName(schemaName,
viewName);
+ String createView = "CREATE VIEW "+viewFullName + "(ID1 BIGINT,
\"id2\" BIGINT NOT NULL, "
+ + "ID3 VARCHAR NOT NULL CONSTRAINT PKVIEW PRIMARY KEY
(\"id2\", ID3 DESC)) "
+ + "AS SELECT * FROM " + pTableFullName + " WHERE \"k\" > 3";
+
+ List<String> queries = new ArrayList<String>(){};
+ queries.add(createTableStmt);
+ queries.add(createView);
+ String result = runSchemaExtractionTool("\"" + schemaName + "\"", "\""
+ viewName + "\"", null, queries);
+ Assert.assertEquals(createView, result);
+ }
+
+ @Test
public void testCreateViewStatement_customName() throws Exception {
String tableName = generateUniqueName();
String schemaName = generateUniqueName();
diff --git
a/phoenix-core/src/main/java/org/apache/phoenix/schema/tool/SchemaExtractionProcessor.java
b/phoenix-core/src/main/java/org/apache/phoenix/schema/tool/SchemaExtractionProcessor.java
index bf6faf9..656bd31 100644
---
a/phoenix-core/src/main/java/org/apache/phoenix/schema/tool/SchemaExtractionProcessor.java
+++
b/phoenix-core/src/main/java/org/apache/phoenix/schema/tool/SchemaExtractionProcessor.java
@@ -97,13 +97,16 @@ public class SchemaExtractionProcessor implements
SchemaProcessor {
protected String extractCreateIndexDDL(PTable indexPTable)
throws SQLException, IOException {
- String pTableName = indexPTable.getTableName().getString();
+ String quotedIndexTableName = SchemaUtil
+ .getFullTableNameWithQuotes(null,
indexPTable.getTableName().getString());
String baseTableName = indexPTable.getParentTableName().getString();
- String baseTableFullName = SchemaUtil
-
.getQualifiedTableName(indexPTable.getSchemaName().getString(), baseTableName);
+ String baseTableFullName = indexPTable.getSchemaName().getString() +
"." + baseTableName;
PTable dataPTable = getPTable(baseTableFullName);
+ String quotedBaseTableFullName = SchemaUtil
+
.getFullTableNameWithQuotes(indexPTable.getSchemaName().getString(),
baseTableName);
+
String defaultCF =
SchemaUtil.getEmptyColumnFamilyAsString(indexPTable);
String indexedColumnsString = getIndexedColumnsString(indexPTable,
dataPTable, defaultCF);
String coveredColumnsString = getCoveredColumnsString(indexPTable,
defaultCF);
@@ -115,8 +118,8 @@ public class SchemaExtractionProcessor implements
SchemaProcessor {
setHTableProperties(htd);
}
String propertiesString = convertPropertiesToString();
- return generateIndexDDLString(baseTableFullName, indexedColumnsString,
coveredColumnsString,
- indexPTable.getIndexType().equals(PTable.IndexType.LOCAL),
pTableName, propertiesString);
+ return generateIndexDDLString(quotedBaseTableFullName,
indexedColumnsString, coveredColumnsString,
+ indexPTable.getIndexType().equals(PTable.IndexType.LOCAL),
quotedIndexTableName, propertiesString);
}
//TODO: Indexed on an expression
@@ -181,11 +184,17 @@ public class SchemaExtractionProcessor implements
SchemaProcessor {
private String extractIndexColumn(String columnName, String defaultCF) {
String [] columnNameSplit = columnName.split(":");
- if(columnNameSplit[0].equals("") ||
columnNameSplit[0].equalsIgnoreCase(defaultCF)) {
- return columnNameSplit[1];
+ if(columnNameSplit[0].equals("") ||
columnNameSplit[0].equalsIgnoreCase(defaultCF) ||
+ (defaultCF.startsWith("L#") &&
columnNameSplit[0].equalsIgnoreCase(defaultCF.substring(2)))) {
+ return SchemaUtil.formatColumnName(columnNameSplit[1]);
} else {
- return columnNameSplit.length > 1 ?
- String.format("\"%s\".\"%s\"", columnNameSplit[0],
columnNameSplit[1]) : columnNameSplit[0];
+ if (columnNameSplit.length > 1) {
+ String schema =
SchemaUtil.formatSchemaName(columnNameSplit[0]);
+ String name = SchemaUtil.formatColumnName(columnNameSplit[1]);
+ return String.format("%s.%s", schema, name);
+ } else {
+ return SchemaUtil.formatColumnName(columnNameSplit[0]);
+ }
}
}
@@ -204,10 +213,10 @@ public class SchemaExtractionProcessor implements
SchemaProcessor {
return coveredColumnsBuilder.toString();
}
- protected String generateIndexDDLString(String baseTableFullName, String
indexedColumnString,
- String coveredColumnString, boolean local, String pTableName,
String properties) {
+ protected String generateIndexDDLString(String quotedBaseTableFullName,
String indexedColumnString,
+ String coveredColumnString, boolean local, String
quotedIndexTableName, String properties) {
StringBuilder outputBuilder = new
StringBuilder(String.format(CREATE_INDEX,
- local ? "LOCAL " : "", pTableName, baseTableFullName));
+ local ? "LOCAL " : "", quotedIndexTableName,
quotedBaseTableFullName));
outputBuilder.append("(");
outputBuilder.append(indexedColumnString);
outputBuilder.append(")");
@@ -230,7 +239,10 @@ public class SchemaExtractionProcessor implements
SchemaProcessor {
String pSchemaName = table.getSchemaName().getString();
String pTableName = table.getTableName().getString();
String baseTableName = table.getParentTableName().getString();
- String baseTableFullName =
SchemaUtil.getQualifiedTableName(pSchemaName, baseTableName);
+ String quotedBaseTableName = SchemaUtil
+ .getFullTableNameWithQuotes(pSchemaName, baseTableName);
+
+ String baseTableFullName = pSchemaName + "." + baseTableName;
PTable baseTable = getPTable(baseTableFullName);
String columnInfoString = getColumnInfoStringForView(table, baseTable);
@@ -238,15 +250,15 @@ public class SchemaExtractionProcessor implements
SchemaProcessor {
if(whereClause != null) {
whereClause = whereClause.substring(whereClause.indexOf("WHERE"));
}
- return generateCreateViewDDL(columnInfoString, baseTableFullName,
+ return generateCreateViewDDL(columnInfoString, quotedBaseTableName,
whereClause == null ? "" : " "+whereClause, pSchemaName,
pTableName);
}
- private String generateCreateViewDDL(String columnInfoString, String
baseTableFullName,
+ private String generateCreateViewDDL(String columnInfoString, String
quotedBaseTableName,
String whereClause, String pSchemaName, String pTableName) {
- String viewFullName =
SchemaUtil.getPTableFullNameWithQuotes(pSchemaName, pTableName);
- StringBuilder outputBuilder = new
StringBuilder(String.format(CREATE_VIEW, viewFullName,
- columnInfoString, baseTableFullName, whereClause));
+ String quotedViewFullName =
SchemaUtil.getFullTableNameWithQuotes(pSchemaName, pTableName);
+ StringBuilder outputBuilder = new
StringBuilder(String.format(CREATE_VIEW,
+ quotedViewFullName, columnInfoString, quotedBaseTableName,
whereClause));
return outputBuilder.toString();
}
@@ -270,8 +282,9 @@ public class SchemaExtractionProcessor implements
SchemaProcessor {
private String generateTableDDLString(String columnInfoString, String
propertiesString,
String pSchemaName, String pTableName) {
- String pTableFullName =
SchemaUtil.getPTableFullNameWithQuotes(pSchemaName, pTableName);
- StringBuilder outputBuilder = new
StringBuilder(String.format(CREATE_TABLE, pTableFullName));
+ String quotedTableFullName =
SchemaUtil.getFullTableNameWithQuotes(pSchemaName, pTableName);
+ StringBuilder outputBuilder = new
StringBuilder(String.format(CREATE_TABLE,
+ quotedTableFullName));
outputBuilder.append(columnInfoString).append("
").append(propertiesString);
return outputBuilder.toString();
}
@@ -455,11 +468,12 @@ public class SchemaExtractionProcessor implements
SchemaProcessor {
}
private String extractColumn(PColumn column) {
- String colName = column.getName().getString();
+ String colName =
SchemaUtil.formatColumnName(column.getName().getString());
if (column.getFamilyName() != null){
- String colFamilyName = column.getFamilyName().getString();
+ String colFamilyName =
SchemaUtil.formatSchemaName(column.getFamilyName().getString());
// check if it is default column family name
- colName =
colFamilyName.equals(QueryConstants.DEFAULT_COLUMN_FAMILY)? colName :
String.format("\"%s\".\"%s\"", colFamilyName, colName);
+ colName =
colFamilyName.equals(QueryConstants.DEFAULT_COLUMN_FAMILY) ? colName :
+ String.format("%s.%s", colFamilyName, colName);
}
boolean isArrayType = column.getDataType().isArrayType();
String type = column.getDataType().getSqlTypeName();
@@ -524,7 +538,7 @@ public class SchemaExtractionProcessor implements
SchemaProcessor {
private String extractPKConstraint(List<PColumn> pkColumns) {
ArrayList<String> colDefs = new ArrayList<>(pkColumns.size());
for (PColumn pkCol : pkColumns) {
- colDefs.add(pkCol.getName().getString() +
extractPKColumnAttributes(pkCol));
+
colDefs.add(SchemaUtil.formatColumnName(pkCol.getName().getString()) +
extractPKColumnAttributes(pkCol));
}
return StringUtils.join(colDefs, ", ");
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
index 311ac98..ed32175 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
@@ -1256,6 +1256,79 @@ public class SchemaUtil {
return columnParseNode.getName();
}
+ public static String getFullTableNameWithQuotes(String schemaName, String
tableName,
+ boolean schemaNameCaseSensitive, boolean tableNameCaseSensitive) {
+ String fullTableName;
+
+ if (tableNameCaseSensitive) {
+ fullTableName = "\"" + tableName + "\"";
+ } else {
+ fullTableName = tableName;
+ }
+
+ if(schemaName != null && schemaName.length() != 0) {
+ if (schemaNameCaseSensitive) {
+ fullTableName = "\"" + schemaName + "\"" +
QueryConstants.NAME_SEPARATOR + fullTableName;
+ } else {
+ fullTableName = schemaName + QueryConstants.NAME_SEPARATOR +
fullTableName;
+ }
+ }
+ return fullTableName;
+ }
+
+ public static String getFullTableNameWithQuotes(String schemaName, String
tableName) {
+ return getFullTableNameWithQuotes(schemaName, tableName,
+ quotesNeededForSchema(schemaName),
quotesNeededForTable(tableName));
+ }
+
+ private static boolean quotesNeededForSchema(String name) {
+ if (Strings.isNullOrEmpty(name) ||
name.equals(QueryConstants.DEFAULT_COLUMN_FAMILY)) {
+ return false;
+ }
+ return quotesNeededForTable(name);
+ }
+
+ private static boolean quotesNeededForColumn(String name) {
+ if (!name.equals("_INDEX_ID") && name.startsWith("_")) {
+ return true;
+ }
+ return isQuotesNeeded(name) || containsLowerCase(name);
+ }
+
+ private static boolean quotesNeededForTable(String name) {
+ if (name.startsWith("_")) {
+ return true;
+ }
+ return isQuotesNeeded(name) || containsLowerCase(name);
+ }
+
+ public static String formatSchemaName(String name) {
+ if (quotesNeededForSchema(name)) {
+ name = "\"" + name + "\"";
+ }
+ return name;
+ }
+
+ public static String formatColumnName(String name) {
+ if (quotesNeededForColumn(name)) {
+ name = "\"" + name + "\"";
+ }
+ return name;
+ }
+
+ public static boolean containsLowerCase(String name) {
+ if (Strings.isNullOrEmpty(name)) {
+ return false;
+ }
+ for (int i=0; i<name.toCharArray().length; i++) {
+ char charAtI = name.charAt(i);
+ if (Character.isLowerCase(charAtI)){
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* This function is needed so that SchemaExtractionTool returns a valid
DDL with correct
* table/schema name that can be parsed