Skip to content

Commit

Permalink
Show original characters for string literals instead of escaping (#675)
Browse files Browse the repository at this point in the history
* Show original characters for string literals instead of escaping

* Make TestWrenWithDuckDBTableFunction be single threaded to avoid concurrent issue
  • Loading branch information
grieve54706 committed Jul 18, 2024
1 parent d320c22 commit daf5a60
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 81 deletions.
64 changes: 5 additions & 59 deletions trino-parser/src/main/java/io/trino/sql/ExpressionFormatter.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.trino.sql;

import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import io.trino.sql.SqlFormatter.Dialect;
Expand Down Expand Up @@ -92,7 +91,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.PrimitiveIterator;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -237,13 +235,13 @@ protected String visitBooleanLiteral(BooleanLiteral node, Void context)
@Override
protected String visitStringLiteral(StringLiteral node, Void context)
{
return formatStringLiteral(node.getValue(), dialect);
return formatStringLiteral(node.getValue());
}

@Override
protected String visitCharLiteral(CharLiteral node, Void context)
{
return "CHAR " + formatStringLiteral(node.getValue(), dialect);
return "CHAR " + formatStringLiteral(node.getValue());
}

@Override
Expand Down Expand Up @@ -327,7 +325,7 @@ protected String visitDecimalLiteral(DecimalLiteral node, Void context)
@Override
protected String visitGenericLiteral(GenericLiteral node, Void context)
{
return node.getType() + " " + formatStringLiteral(node.getValue(), dialect);
return node.getType() + " " + formatStringLiteral(node.getValue());
}

@Override
Expand Down Expand Up @@ -998,61 +996,9 @@ private String processDateDiffInBigQuery(FunctionCall node, Void context)
}
}

static String formatStringLiteral(String s, Dialect dialect)
static String formatStringLiteral(String s)
{
if (dialect == BIGQUERY) {
s = s.replace("'", "\\'");
}
else {
s = s.replace("'", "''");
}
if (CharMatcher.inRange((char) 0x20, (char) 0x7E).matchesAllOf(s)) {
return "'" + s + "'";
}

StringBuilder builder = new StringBuilder();
if (dialect == DEFAULT || dialect == DUCKDB || dialect == POSTGRES) {
builder.append("U&");
}
builder.append("'");
PrimitiveIterator.OfInt iterator = s.codePoints().iterator();
while (iterator.hasNext()) {
int codePoint = iterator.nextInt();
checkArgument(codePoint >= 0, "Invalid UTF-8 encoding in characters: %s", s);
if (isAsciiPrintable(codePoint)) {
char ch = (char) codePoint;
if (ch == '\\') {
builder.append(ch);
}
builder.append(ch);
}
else {
if (dialect == DEFAULT || dialect == DUCKDB || dialect == POSTGRES) {
if (codePoint <= 0xFFFF) {
builder.append('\\');
builder.append(format("%04X", codePoint));
}
else {
builder.append("\\+");
builder.append(format("%06X", codePoint));
}
}
else if (dialect == BIGQUERY) {
if (codePoint <= 0xFFFF) {
builder.append('\\');
builder.append('u');
builder.append(format("%04X", codePoint));
}
else {
builder.append("\\");
builder.append('U');
builder.append(format("%08X", codePoint));
}
}
}
}
builder.append("'");
return builder.toString();
return "'" + s.replace("'", "''") + "'";
}

public static String formatOrderBy(OrderBy orderBy, Dialect dialect)
Expand Down
36 changes: 18 additions & 18 deletions trino-parser/src/main/java/io/trino/sql/SqlFormatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ protected Void visitCreateView(CreateView node, Integer indent)

node.getComment().ifPresent(comment -> builder
.append(" COMMENT ")
.append(formatStringLiteral(comment, dialect)));
.append(formatStringLiteral(comment)));

node.getSecurity().ifPresent(security -> builder
.append(" SECURITY ")
Expand Down Expand Up @@ -957,7 +957,7 @@ protected Void visitCreateMaterializedView(CreateMaterializedView node, Integer
builder.append(formatName(node.getName(), dialect));
node.getComment().ifPresent(comment -> builder
.append("\nCOMMENT ")
.append(formatStringLiteral(comment, dialect)));
.append(formatStringLiteral(comment)));
builder.append(formatPropertiesMultiLine(node.getProperties()));
builder.append(" AS\n");

Expand Down Expand Up @@ -1051,11 +1051,11 @@ protected Void visitShowCatalogs(ShowCatalogs node, Integer indent)

node.getLikePattern().ifPresent(value -> builder
.append(" LIKE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

node.getEscape().ifPresent(value -> builder
.append(" ESCAPE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

return null;
}
Expand All @@ -1071,11 +1071,11 @@ protected Void visitShowSchemas(ShowSchemas node, Integer indent)

node.getLikePattern().ifPresent(value -> builder
.append(" LIKE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

node.getEscape().ifPresent(value -> builder
.append(" ESCAPE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

return null;
}
Expand All @@ -1091,11 +1091,11 @@ protected Void visitShowTables(ShowTables node, Integer indent)

node.getLikePattern().ifPresent(value -> builder
.append(" LIKE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

node.getEscape().ifPresent(value -> builder
.append(" ESCAPE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

return null;
}
Expand Down Expand Up @@ -1126,11 +1126,11 @@ protected Void visitShowColumns(ShowColumns node, Integer indent)

node.getLikePattern().ifPresent(value -> builder
.append(" LIKE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

node.getEscape().ifPresent(value -> builder
.append(" ESCAPE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

return null;
}
Expand All @@ -1151,11 +1151,11 @@ protected Void visitShowFunctions(ShowFunctions node, Integer indent)

node.getLikePattern().ifPresent(value -> builder
.append(" LIKE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

node.getEscape().ifPresent(value -> builder
.append(" ESCAPE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

return null;
}
Expand All @@ -1167,11 +1167,11 @@ protected Void visitShowSession(ShowSession node, Integer indent)

node.getLikePattern().ifPresent(value -> builder
.append(" LIKE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

node.getEscape().ifPresent(value -> builder
.append(" ESCAPE ")
.append(formatStringLiteral(value, dialect)));
.append(formatStringLiteral(value)));

return null;
}
Expand Down Expand Up @@ -1259,7 +1259,7 @@ protected Void visitCreateTableAsSelect(CreateTableAsSelect node, Integer indent

node.getComment().ifPresent(comment -> builder
.append("\nCOMMENT ")
.append(formatStringLiteral(comment, dialect)));
.append(formatStringLiteral(comment)));
builder.append(formatPropertiesMultiLine(node.getProperties()));

builder.append(" AS ");
Expand Down Expand Up @@ -1310,7 +1310,7 @@ protected Void visitCreateTable(CreateTable node, Integer indent)

node.getComment().ifPresent(comment -> builder
.append("\nCOMMENT ")
.append(formatStringLiteral(comment, dialect)));
.append(formatStringLiteral(comment)));

builder.append(formatPropertiesMultiLine(node.getProperties()));

Expand Down Expand Up @@ -1351,7 +1351,7 @@ private String formatColumnDefinition(ColumnDefinition column)
}
column.getComment().ifPresent(comment -> builder
.append(" COMMENT ")
.append(formatStringLiteral(comment, dialect)));
.append(formatStringLiteral(comment)));
builder.append(formatPropertiesSingleLine(column.getProperties()));
return builder.toString();
}
Expand Down Expand Up @@ -1442,7 +1442,7 @@ private String joinProperties(List<Property> properties)
protected Void visitComment(Comment node, Integer context)
{
String comment = node.getComment()
.map(str -> formatStringLiteral(str, dialect))
.map(ExpressionFormatter::formatStringLiteral)
.orElse("NULL");

switch (node.getType()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,11 +331,14 @@ public void testStatementBuilder()
public void testStringFormatter()
{
assertSqlFormatter("U&'hello\\6d4B\\8Bd5\\+10FFFFworld\\7F16\\7801'",
"U&'hello\\6D4B\\8BD5\\+10FFFFworld\\7F16\\7801'");
"'hello测试\uDBFF\uDFFFworld编码'");
assertSqlFormatter("'hello world'", "'hello world'");
assertSqlFormatter("U&'!+10FFFF!6d4B!8Bd5ABC!6d4B!8Bd5' UESCAPE '!'", "U&'\\+10FFFF\\6D4B\\8BD5ABC\\6D4B\\8BD5'");
assertSqlFormatter("U&'\\+10FFFF\\6D4B\\8BD5\\0041\\0042\\0043\\6D4B\\8BD5'", "U&'\\+10FFFF\\6D4B\\8BD5ABC\\6D4B\\8BD5'");
assertSqlFormatter("U&'\\\\abc\\6D4B'''", "U&'\\\\abc\\6D4B'''");
assertSqlFormatter("U&'!+10FFFF!6d4B!8Bd5ABC!6d4B!8Bd5' UESCAPE '!'", "'\uDBFF\uDFFF测试ABC测试'");
assertSqlFormatter("U&'\\+10FFFF\\6D4B\\8BD5\\0041\\0042\\0043\\6D4B\\8BD5'", "'\uDBFF\uDFFF测试ABC测试'");
assertSqlFormatter("U&'\\\\abc\\6D4B'''", "'\\abc测'''");
assertSqlFormatter("'攻殻機動隊'", "'攻殻機動隊'");
assertSqlFormatter("'😂'", "'😂'");
assertSqlFormatter("'시험'", "'시험'");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import static java.util.Objects.requireNonNull;
import static org.assertj.core.api.Assertions.assertThat;

@Test(singleThreaded = true)
public class TestWrenWithDuckDBTableFunction
extends RequireWrenServer
{
Expand Down

0 comments on commit daf5a60

Please sign in to comment.