Skip to content

Commit 3ebd933

Browse files
committed
[Feature][Transform] support boolean type for sql transform
1 parent 5f55e31 commit 3ebd933

File tree

4 files changed

+140
-0
lines changed

4 files changed

+140
-0
lines changed

seatunnel-transforms-v2/src/main/java/org/apache/seatunnel/transform/sql/zeta/ZetaSQLFunction.java

+7
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
6060
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
6161
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
62+
import net.sf.jsqlparser.parser.Node;
6263
import net.sf.jsqlparser.schema.Column;
6364
import net.sf.jsqlparser.statement.select.LateralView;
6465

@@ -263,6 +264,12 @@ public Object computeForValue(Expression expression, Object[] inputFields) {
263264
if (expression instanceof Column) {
264265
Column columnExp = (Column) expression;
265266
String columnName = columnExp.getColumnName();
267+
Node node = columnExp.getASTNode().jjtGetParent();
268+
if (("true".equalsIgnoreCase(columnExp.getColumnName())
269+
|| "false".equalsIgnoreCase(columnExp.getColumnName()))
270+
&& ("CaseWhenExpression".equalsIgnoreCase(node.toString()))) {
271+
return Boolean.parseBoolean(columnExp.getColumnName());
272+
}
266273
int index = inputRowType.indexOf(columnName, false);
267274
if (index == -1
268275
&& columnName.startsWith(ZetaSQLEngine.ESCAPE_IDENTIFIER)

seatunnel-transforms-v2/src/main/java/org/apache/seatunnel/transform/sql/zeta/ZetaSQLType.java

+10
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
5757
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
5858
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
59+
import net.sf.jsqlparser.parser.Node;
5960
import net.sf.jsqlparser.schema.Column;
6061

6162
import java.util.ArrayList;
@@ -81,6 +82,7 @@ public class ZetaSQLType {
8182
public static final String DATETIME = "DATETIME";
8283
public static final String DATE = "DATE";
8384
public static final String TIME = "TIME";
85+
public static final String BOOLEAN = "BOOLEAN";
8486

8587
private final SeaTunnelRowType inputRowType;
8688

@@ -113,6 +115,12 @@ public SeaTunnelDataType<?> getExpressionType(Expression expression) {
113115
}
114116
if (expression instanceof Column) {
115117
Column columnExp = (Column) expression;
118+
Node node = columnExp.getASTNode().jjtGetParent();
119+
if (("true".equalsIgnoreCase(columnExp.getColumnName())
120+
|| "false".equalsIgnoreCase(columnExp.getColumnName()))
121+
&& ("CaseWhenExpression".equalsIgnoreCase(node.toString()))) {
122+
return BasicType.BOOLEAN_TYPE;
123+
}
116124
String columnName = columnExp.getColumnName();
117125
int index = inputRowType.indexOf(columnName, false);
118126
if (index == -1
@@ -352,6 +360,8 @@ private SeaTunnelDataType<?> getCastType(CastExpression castExpression) {
352360
return LocalTimeType.LOCAL_DATE_TYPE;
353361
case TIME:
354362
return LocalTimeType.LOCAL_TIME_TYPE;
363+
case BOOLEAN:
364+
return BasicType.BOOLEAN_TYPE;
355365
default:
356366
throw new TransformException(
357367
CommonErrorCodeDeprecated.UNSUPPORTED_OPERATION,

seatunnel-transforms-v2/src/main/java/org/apache/seatunnel/transform/sql/zeta/functions/SystemFunction.java

+21
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.time.LocalTime;
3434
import java.time.ZoneId;
3535
import java.util.ArrayList;
36+
import java.util.Arrays;
3637
import java.util.List;
3738

3839
public class SystemFunction {
@@ -177,6 +178,26 @@ public static Object castAs(List<Object> args) {
177178
BigDecimal bigDecimal = new BigDecimal(v1.toString());
178179
Integer scale = (Integer) args.get(3);
179180
return bigDecimal.setScale(scale, RoundingMode.CEILING);
181+
case "BOOLEAN":
182+
if (v1 instanceof Number) {
183+
if (Arrays.asList(1, 0).contains(((Number) v1).intValue())) {
184+
return ((Number) v1).intValue() == 1;
185+
} else {
186+
throw new TransformException(
187+
CommonErrorCodeDeprecated.UNSUPPORTED_OPERATION,
188+
String.format("Unsupported CAST AS Boolean: %s", v1));
189+
}
190+
} else if (v1 instanceof String) {
191+
if (Arrays.asList("TRUE", "FALSE").contains(v1.toString().toUpperCase())) {
192+
return Boolean.parseBoolean(v1.toString());
193+
} else {
194+
throw new TransformException(
195+
CommonErrorCodeDeprecated.UNSUPPORTED_OPERATION,
196+
String.format("Unsupported CAST AS Boolean: %s", v1));
197+
}
198+
} else if (v1 instanceof Boolean) {
199+
return v1;
200+
}
180201
}
181202
throw new TransformException(
182203
CommonErrorCodeDeprecated.UNSUPPORTED_OPERATION,

seatunnel-transforms-v2/src/test/java/org/apache/seatunnel/transform/sql/SQLTransformTest.java

+102
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.seatunnel.api.table.type.SeaTunnelDataType;
3030
import org.apache.seatunnel.api.table.type.SeaTunnelRow;
3131
import org.apache.seatunnel.api.table.type.SeaTunnelRowType;
32+
import org.apache.seatunnel.transform.exception.TransformException;
3233

3334
import org.junit.jupiter.api.Assertions;
3435
import org.junit.jupiter.api.Test;
@@ -315,4 +316,105 @@ public void tesCaseWhenClausesWithBooleanField() {
315316
Assertions.assertEquals(false, result.get(0).getField(1));
316317
Assertions.assertEquals(2, result.get(0).getField(2));
317318
}
319+
320+
@Test
321+
public void tesCaseWhenBooleanClausesWithField() {
322+
String tableName = "test";
323+
String[] fields = new String[] {"id", "int", "string"};
324+
CatalogTable table =
325+
CatalogTableUtil.getCatalogTable(
326+
tableName,
327+
new SeaTunnelRowType(
328+
fields,
329+
new SeaTunnelDataType[] {
330+
BasicType.INT_TYPE, BasicType.INT_TYPE, BasicType.STRING_TYPE
331+
}));
332+
ReadonlyConfig config =
333+
ReadonlyConfig.fromMap(
334+
Collections.singletonMap(
335+
"query",
336+
"select `id`, `int`, (case when `int` = 1 then true else false end) as bool_1 , `string`, (case when `string` = 'true' then true else false end) as bool_2 from dual"));
337+
SQLTransform sqlTransform = new SQLTransform(config, table);
338+
List<SeaTunnelRow> result =
339+
sqlTransform.transformRow(new SeaTunnelRow(new Object[] {1, 1, "true"}));
340+
341+
Assertions.assertEquals(1, result.get(0).getField(0));
342+
Assertions.assertEquals(1, result.get(0).getField(1));
343+
Assertions.assertEquals(true, result.get(0).getField(2));
344+
Assertions.assertEquals("true", result.get(0).getField(3));
345+
Assertions.assertEquals(true, result.get(0).getField(4));
346+
347+
result = sqlTransform.transformRow(new SeaTunnelRow(new Object[] {1, 0, "false"}));
348+
Assertions.assertEquals(1, result.get(0).getField(0));
349+
Assertions.assertEquals(0, result.get(0).getField(1));
350+
Assertions.assertEquals(false, result.get(0).getField(2));
351+
Assertions.assertEquals("false", result.get(0).getField(3));
352+
Assertions.assertEquals(false, result.get(0).getField(4));
353+
}
354+
355+
@Test
356+
public void tesCastBooleanClausesWithField() {
357+
String tableName = "test";
358+
String[] fields = new String[] {"id", "int", "string"};
359+
CatalogTable table =
360+
CatalogTableUtil.getCatalogTable(
361+
tableName,
362+
new SeaTunnelRowType(
363+
fields,
364+
new SeaTunnelDataType[] {
365+
BasicType.INT_TYPE, BasicType.INT_TYPE, BasicType.STRING_TYPE
366+
}));
367+
ReadonlyConfig config =
368+
ReadonlyConfig.fromMap(
369+
Collections.singletonMap(
370+
"query",
371+
"select `id`, `int`, cast(`int` as boolean) as bool_1 , `string`, cast(`string` as boolean) as bool_2 from dual"));
372+
SQLTransform sqlTransform = new SQLTransform(config, table);
373+
List<SeaTunnelRow> result =
374+
sqlTransform.transformRow(
375+
new SeaTunnelRow(new Object[] {Integer.valueOf(1), 1, "true"}));
376+
377+
Assertions.assertEquals(1, result.get(0).getField(0));
378+
Assertions.assertEquals(1, result.get(0).getField(1));
379+
Assertions.assertEquals(true, result.get(0).getField(2));
380+
Assertions.assertEquals("true", result.get(0).getField(3));
381+
Assertions.assertEquals(true, result.get(0).getField(4));
382+
383+
result =
384+
sqlTransform.transformRow(
385+
new SeaTunnelRow(new Object[] {Integer.valueOf(1), 0, "false"}));
386+
Assertions.assertEquals(1, result.get(0).getField(0));
387+
Assertions.assertEquals(0, result.get(0).getField(1));
388+
Assertions.assertEquals(false, result.get(0).getField(2));
389+
Assertions.assertEquals("false", result.get(0).getField(3));
390+
Assertions.assertEquals(false, result.get(0).getField(4));
391+
392+
Assertions.assertThrows(
393+
TransformException.class,
394+
() -> {
395+
try {
396+
sqlTransform.transformRow(
397+
new SeaTunnelRow(new Object[] {Integer.valueOf(1), 3, "false"}));
398+
} catch (Exception e) {
399+
Assertions.assertEquals(
400+
"ErrorCode:[COMMON-05], ErrorDescription:[Unsupported operation] - Unsupported CAST AS Boolean: 3",
401+
e.getMessage());
402+
throw e;
403+
}
404+
});
405+
406+
Assertions.assertThrows(
407+
TransformException.class,
408+
() -> {
409+
try {
410+
sqlTransform.transformRow(
411+
new SeaTunnelRow(new Object[] {Integer.valueOf(1), 0, "false333"}));
412+
} catch (Exception e) {
413+
Assertions.assertEquals(
414+
"ErrorCode:[COMMON-05], ErrorDescription:[Unsupported operation] - Unsupported CAST AS Boolean: false333",
415+
e.getMessage());
416+
throw e;
417+
}
418+
});
419+
}
318420
}

0 commit comments

Comments
 (0)