Skip to content

Commit a34cfac

Browse files
authored
fix: deparse casts to single-field row types (#2757)
1 parent 13a9dda commit a34cfac

3 files changed

Lines changed: 33 additions & 13 deletions

File tree

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,17 @@
99
*/
1010
package net.sf.jsqlparser.expression;
1111

12-
import java.util.Locale;
13-
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
14-
import net.sf.jsqlparser.statement.create.table.ColDataType;
15-
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
16-
import net.sf.jsqlparser.statement.select.Select;
17-
1812
import java.util.ArrayList;
13+
import java.util.Locale;
1914
import java.util.Set;
2015
import java.util.logging.Level;
2116
import java.util.logging.Logger;
2217
import java.util.regex.Matcher;
2318
import java.util.regex.Pattern;
19+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
20+
import net.sf.jsqlparser.statement.create.table.ColDataType;
21+
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
22+
import net.sf.jsqlparser.statement.select.Select;
2423

2524
public class CastExpression extends ASTNodeAccessImpl implements Expression {
2625
private final static Pattern PATTERN =
@@ -204,7 +203,7 @@ public String toString() {
204203
if (isImplicitCast) {
205204
return colDataType + " " + leftExpression;
206205
} else if (keyword != null && !keyword.isEmpty()) {
207-
return columnDefinitions.size() > 1
206+
return !columnDefinitions.isEmpty()
208207
? keyword + "(" + leftExpression + " AS ROW("
209208
+ Select.getStringList(columnDefinitions) + ")" + formatStr + ")"
210209
: keyword + "(" + leftExpression + " AS " + colDataType.toString() + formatStr

‎src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99
*/
1010
package net.sf.jsqlparser.util.deparser;
1111

12-
import net.sf.jsqlparser.expression.AliasedExpression;
13-
1412
import static java.util.stream.Collectors.joining;
1513

1614
import java.util.Iterator;
1715
import java.util.List;
1816
import java.util.Map;
17+
import net.sf.jsqlparser.expression.AliasedExpression;
1918
import net.sf.jsqlparser.expression.AllValue;
2019
import net.sf.jsqlparser.expression.AnalyticExpression;
2120
import net.sf.jsqlparser.expression.AnalyticType;
@@ -42,7 +41,6 @@
4241
import net.sf.jsqlparser.expression.HexValue;
4342
import net.sf.jsqlparser.expression.HighExpression;
4443
import net.sf.jsqlparser.expression.IntervalExpression;
45-
import net.sf.jsqlparser.expression.RowPatternFunction;
4644
import net.sf.jsqlparser.expression.Inverse;
4745
import net.sf.jsqlparser.expression.JdbcNamedParameter;
4846
import net.sf.jsqlparser.expression.JdbcParameter;
@@ -56,6 +54,7 @@
5654
import net.sf.jsqlparser.expression.LongValue;
5755
import net.sf.jsqlparser.expression.LowExpression;
5856
import net.sf.jsqlparser.expression.MapExpression;
57+
import net.sf.jsqlparser.expression.MethodCallExpression;
5958
import net.sf.jsqlparser.expression.MySQLGroupConcat;
6059
import net.sf.jsqlparser.expression.NextValExpression;
6160
import net.sf.jsqlparser.expression.NotExpression;
@@ -69,7 +68,7 @@
6968
import net.sf.jsqlparser.expression.RangeExpression;
7069
import net.sf.jsqlparser.expression.RowConstructor;
7170
import net.sf.jsqlparser.expression.RowGetExpression;
72-
import net.sf.jsqlparser.expression.MethodCallExpression;
71+
import net.sf.jsqlparser.expression.RowPatternFunction;
7372
import net.sf.jsqlparser.expression.SignedExpression;
7473
import net.sf.jsqlparser.expression.StringValue;
7574
import net.sf.jsqlparser.expression.StructType;
@@ -119,9 +118,9 @@
119118
import net.sf.jsqlparser.expression.operators.relational.Intersects;
120119
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
121120
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
121+
import net.sf.jsqlparser.expression.operators.relational.IsJsonExpression;
122122
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
123123
import net.sf.jsqlparser.expression.operators.relational.IsUnknownExpression;
124-
import net.sf.jsqlparser.expression.operators.relational.IsJsonExpression;
125124
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
126125
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
127126
import net.sf.jsqlparser.expression.operators.relational.Matches;
@@ -1181,7 +1180,7 @@ public <S> StringBuilder visit(CastExpression cast, S context) {
11811180
cast.getLeftExpression().accept(this, context);
11821181
builder.append(" AS ");
11831182
builder.append(
1184-
cast.getColumnDefinitions().size() > 1
1183+
!cast.getColumnDefinitions().isEmpty()
11851184
? "ROW(" + Select.getStringList(cast.getColumnDefinitions()) + ")"
11861185
: cast.getColDataType().toString());
11871186
builder.append(formatStr);

‎src/test/java/net/sf/jsqlparser/expression/CastExpressionTest.java‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
1717
import net.sf.jsqlparser.statement.select.PlainSelect;
1818
import net.sf.jsqlparser.test.TestUtils;
19+
import net.sf.jsqlparser.util.deparser.StatementDeParser;
1920
import org.junit.jupiter.api.Assertions;
2021
import org.junit.jupiter.api.Test;
2122

@@ -25,6 +26,27 @@
2526
*/
2627
public class CastExpressionTest {
2728

29+
@Test
30+
void testCastToSingleFieldRow() throws JSQLParserException {
31+
String sql = "SELECT CAST(ROW(1) AS ROW(x BIGINT))";
32+
PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sql);
33+
CastExpression cast = Assertions.assertInstanceOf(CastExpression.class,
34+
select.getSelectItem(0).getExpression());
35+
Assertions.assertEquals(1, cast.getColumnDefinitions().size());
36+
Assertions.assertEquals("x", cast.getColumnDefinitions().get(0).getColumnName());
37+
Assertions.assertEquals("BIGINT",
38+
cast.getColumnDefinitions().get(0).getColDataType().getDataType());
39+
40+
Assertions.assertAll(
41+
() -> assertSqlCanBeParsedAndDeparsed(sql),
42+
() -> {
43+
StringBuilder builder = new StringBuilder();
44+
select.accept(new StatementDeParser(builder));
45+
Assertions.assertEquals(sql, builder.toString());
46+
});
47+
assertSqlCanBeParsedAndDeparsed("SELECT TRY_CAST(ROW(1) AS ROW(x BIGINT))");
48+
}
49+
2850
@Test
2951
public void testCastToRowConstructorIssue1267() throws JSQLParserException {
3052
TestUtils.assertExpressionCanBeParsedAndDeparsed(

0 commit comments

Comments
 (0)