Skip to content

Commit

Permalink
Quote reserved identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
nevillelyh authored and martint committed Aug 30, 2022
1 parent 441889c commit b076313
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.getOnlyElement;
import static io.trino.sql.ReservedIdentifiers.reserved;
import static io.trino.sql.RowPatternFormatter.formatPattern;
import static io.trino.sql.SqlFormatter.formatName;
import static io.trino.sql.SqlFormatter.formatSql;
Expand Down Expand Up @@ -401,12 +402,10 @@ protected String visitExists(ExistsPredicate node, Void context)
@Override
protected String visitIdentifier(Identifier node, Void context)
{
if (!node.isDelimited()) {
return node.getValue();
}
else {
if (node.isDelimited() || reserved(node.getValue())) {
return '"' + node.getValue().replace("\"", "\"\"") + '"';
}
return node.getValue();
}

@Override
Expand Down
81 changes: 81 additions & 0 deletions core/trino-parser/src/test/java/io/trino/sql/TestSqlFormatter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Licensed 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 io.trino.sql;

import com.google.common.collect.ImmutableList;
import io.trino.sql.tree.ColumnDefinition;
import io.trino.sql.tree.CreateTable;
import io.trino.sql.tree.GenericDataType;
import io.trino.sql.tree.Identifier;
import io.trino.sql.tree.NodeLocation;
import io.trino.sql.tree.QualifiedName;
import org.junit.jupiter.api.Test;

import java.util.Optional;
import java.util.function.BiFunction;

import static io.trino.sql.SqlFormatter.formatSql;
import static org.assertj.core.api.Assertions.assertThat;

public class TestSqlFormatter
{
@Test
public void testIdentifiers()
{
// Reserved keyword
assertThat(formatSql(new Identifier("exists", false))).isEqualTo("\"exists\"");
assertThat(formatSql(new Identifier("exists", true))).isEqualTo("\"exists\"");
assertThat(formatSql(new Identifier("\"exists\"", true))).isEqualTo("\"\"\"exists\"\"\"");

// Non-reserved keyword
assertThat(formatSql(new Identifier("analyze", false))).isEqualTo("analyze");
assertThat(formatSql(new Identifier("analyze", true))).isEqualTo("\"analyze\"");
assertThat(formatSql(new Identifier("\"analyze\"", true))).isEqualTo("\"\"\"analyze\"\"\"");

// ANSI-compliant identifier
assertThat(formatSql(new Identifier("account", false))).isEqualTo("account");
assertThat(formatSql(new Identifier("account", true))).isEqualTo("\"account\"");
assertThat(formatSql(new Identifier("\"account\"", true))).isEqualTo("\"\"\"account\"\"\"");

// Non-ANSI compliant identifier
assertThat(formatSql(new Identifier("1", true))).isEqualTo("\"1\"");
assertThat(formatSql(new Identifier("\"1\"", true))).isEqualTo("\"\"\"1\"\"\"");
}

@Test
public void testCreateTable()
{
BiFunction<String, String, CreateTable> createTable = (tableName, columnName) -> {
NodeLocation location = new NodeLocation(1, 1);
Identifier type = new Identifier(location, "VARCHAR", false);
return new CreateTable(
QualifiedName.of(ImmutableList.of(new Identifier(tableName, false))),
ImmutableList.of(new ColumnDefinition(
new Identifier(columnName, false),
new GenericDataType(location, type, ImmutableList.of()),
true,
ImmutableList.of(),
Optional.empty())),
false,
ImmutableList.of(),
Optional.empty());
};
String createTableSql = "CREATE TABLE %s (\n %s VARCHAR\n)";

assertThat(formatSql(createTable.apply("table_name", "column_name")))
.isEqualTo(String.format(createTableSql, "table_name", "column_name"));
assertThat(formatSql(createTable.apply("exists", "exists")))
.isEqualTo(String.format(createTableSql, "\"exists\"", "\"exists\""));
}
}

0 comments on commit b076313

Please sign in to comment.