Skip to content

Commit 0031943

Browse files
authored
fix: preserve JSON_TABLE EXISTS column order (#2682)
Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent b62bb62 commit 0031943

2 files changed

Lines changed: 88 additions & 3 deletions

File tree

‎src/main/java/net/sf/jsqlparser/expression/JsonTableFunction.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -620,9 +620,6 @@ public String toString() {
620620
builder.append(" FOR ORDINALITY");
621621
return builder.toString();
622622
}
623-
if (exists) {
624-
builder.append(" EXISTS");
625-
}
626623
if (dataType != null) {
627624
builder.append(" ").append(dataType);
628625
}
@@ -637,6 +634,9 @@ public String toString() {
637634
builder.append(scalarsType);
638635
builder.append(" SCALARS");
639636
}
637+
if (exists) {
638+
builder.append(" EXISTS");
639+
}
640640
if (wrapperClause != null && wrapperClause.isBeforePathExpression()) {
641641
builder.append(" ").append(wrapperClause);
642642
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.expression;
11+
12+
import net.sf.jsqlparser.JSQLParserException;
13+
import net.sf.jsqlparser.expression.JsonTableFunction.JsonTableValueColumnDefinition;
14+
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
15+
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
16+
import net.sf.jsqlparser.statement.create.table.ColDataType;
17+
import net.sf.jsqlparser.statement.select.PlainSelect;
18+
import net.sf.jsqlparser.statement.select.TableFunction;
19+
import net.sf.jsqlparser.test.TestUtils;
20+
import org.junit.jupiter.api.Test;
21+
import org.junit.jupiter.params.ParameterizedTest;
22+
import org.junit.jupiter.params.provider.ValueSource;
23+
24+
import static org.junit.jupiter.api.Assertions.*;
25+
26+
class JsonTableExistsTest {
27+
@ParameterizedTest
28+
@ValueSource(strings = {
29+
"n INT EXISTS PATH '$.n'",
30+
"n VARCHAR(10) EXISTS PATH '$.n'",
31+
"NESTED PATH '$.items[*]' COLUMNS (n INT EXISTS PATH '$.n')"
32+
})
33+
void typedExistsRoundTrips(String column) throws JSQLParserException {
34+
String sql = sql(column);
35+
for (Dialect dialect : new Dialect[] {null, Dialect.MYSQL, Dialect.ORACLE}) {
36+
PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sql,
37+
true, parser -> {
38+
if (dialect != null) {
39+
parser.withDialect(dialect);
40+
}
41+
});
42+
TestUtils.assertSqlCanBeParsedAndDeparsed(select.toString(), false,
43+
parser -> {
44+
if (dialect != null) {
45+
parser.withDialect(dialect);
46+
}
47+
});
48+
}
49+
}
50+
51+
@Test
52+
void typedExistsCanBeInspectedAndEdited() throws JSQLParserException {
53+
PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sql("n INT EXISTS PATH '$.n'"));
54+
JsonTableFunction table =
55+
(JsonTableFunction) ((TableFunction) select.getFromItem()).getFunction();
56+
JsonTableValueColumnDefinition column =
57+
(JsonTableValueColumnDefinition) table.getColumnsClause().getColumnDefinitions()
58+
.get(0);
59+
assertTrue(column.isExists());
60+
assertEquals("INT", column.getDataType().getBaseTypeName());
61+
column.setColumnName("present").setDataType(new ColDataType("BIGINT"))
62+
.setPathExpression(new StringValue("$.other"));
63+
TestUtils.assertStatementCanBeDeparsedAs(select,
64+
sql("present BIGINT EXISTS PATH '$.other'"), true);
65+
TestUtils.assertSqlCanBeParsedAndDeparsed(select.toString());
66+
column.setExistsKeyword(false);
67+
TestUtils.assertStatementCanBeDeparsedAs(select, sql("present BIGINT PATH '$.other'"),
68+
true);
69+
}
70+
71+
@Test
72+
void constructedAndUntypedExistsColumnsRetainOrder() throws JSQLParserException {
73+
JsonTableValueColumnDefinition column = new JsonTableValueColumnDefinition()
74+
.setColumnName("n").setExistsKeyword(true).setDataType(new ColDataType("INT"))
75+
.setPathExpression(new StringValue("$.n"));
76+
assertEquals("n INT EXISTS PATH '$.n'", column.toString());
77+
column.setDataType(null);
78+
assertEquals("n EXISTS PATH '$.n'", column.toString());
79+
TestUtils.assertSqlCanBeParsedAndDeparsed(sql(column.toString()));
80+
}
81+
82+
private static String sql(String column) {
83+
return "SELECT * FROM JSON_TABLE('[{\"n\":1},{}]', '$[*]' COLUMNS (" + column + ")) AS jt";
84+
}
85+
}

0 commit comments

Comments
 (0)