in src/main/java/com/google/cloud/spanner/pgadapter/statements/TableParser.java [108:193]
private boolean parseTableList(
ImmutableMap<TableOrIndexName, TableOrIndexName> detectAndReplaceMap,
Set<TableOrIndexName> replacedTables,
ImmutableSet.Builder<TableOrIndexName> detectedTablesBuilder,
boolean multipleTables) {
boolean detectedOrReplacedTable = false;
boolean wasJoin = false;
do {
if (parser.eatToken("(")) {
int startPosition = parser.getPos();
String subExpression = parser.eatSubExpression();
TableParser subParser = new TableParser(Statement.of(subExpression));
Tuple<Set<TableOrIndexName>, Statement> subResult =
subParser.detectAndReplaceTables(
detectAndReplaceMap,
replacedTables,
subParser.parser.peekKeyword("select") || subParser.parser.peekKeyword("with"));
if (!subResult.x().isEmpty()) {
detectedOrReplacedTable = true;
detectedTablesBuilder.addAll(subResult.x());
parser.setSql(
parser.getSql().substring(0, startPosition)
+ subResult.y().getSql()
+ parser.getSql().substring(parser.getPos()));
// Set the position of the parser to after the replaced sub-expression.
parser.setPos(startPosition + subResult.y().getSql().length());
parser.eatToken(")");
}
} else {
// Skip all whitespaces to get the actual position before the next table name.
parser.skipWhitespaces();
int positionBeforeName = parser.getPos();
TableOrIndexName tableOrIndexName = parser.readTableOrIndexName();
if (tableOrIndexName == null) {
break;
}
if (detectAndReplaceMap.containsKey(tableOrIndexName)) {
detectedOrReplacedTable = true;
// Add the translated table name to the set of discovered tables so that a CTE can be
// added for it.
detectedTablesBuilder.add(
Objects.requireNonNull(detectAndReplaceMap.get(tableOrIndexName)));
replacedTables.add(tableOrIndexName);
// Check if the entry in the table map contains a different replacement value than the
// original. Some tables may be added to the map of replacements with the same replacement
// value as the original with the sole purpose of detecting the use of the table.
if (!Objects.equals(detectAndReplaceMap.get(tableOrIndexName), tableOrIndexName)) {
parser.setSql(
parser.getSql().substring(0, positionBeforeName)
+ detectAndReplaceMap.get(tableOrIndexName)
+ parser.getSql().substring(parser.getPos()));
// Set the position of the parser to after the replaced table name.
parser.setPos(
positionBeforeName
+ Objects.requireNonNull(detectAndReplaceMap.get(tableOrIndexName))
.toString()
.length());
}
}
}
// Skip any aliases.
if (multipleTables && !parser.peekJoinKeyword()) {
parser.eatKeyword("as");
parser.readIdentifierPart();
}
if (wasJoin) {
// Skip the join condition.
int positionBeforeJoinCondition = parser.getPos();
parser.eatJoinCondition();
// Replace fully-qualified table names with unqualified table names in the join condition.
String joinCondition =
replaceFullyQualifiedColumnNames(
detectAndReplaceMap, replacedTables, positionBeforeJoinCondition, parser.getPos());
if (joinCondition != null) {
parser.setSql(
parser.getSql().substring(0, positionBeforeJoinCondition)
+ joinCondition
+ parser.getSql().substring(parser.getPos()));
// Set the position of the parser to after the replaced join condition.
parser.setPos(positionBeforeJoinCondition + joinCondition.length());
}
}
} while (multipleTables && (parser.eatToken(",") || (wasJoin = parser.eatJoinType())));
return detectedOrReplacedTable;
}