|
17 | 17 |
|
18 | 18 | package org.apache.wayang.api.sql; |
19 | 19 |
|
| 20 | +import org.apache.calcite.jdbc.CalciteSchema; |
20 | 21 | import org.apache.calcite.jdbc.JavaTypeFactoryImpl; |
21 | 22 | import org.apache.calcite.rel.RelNode; |
22 | 23 | import org.apache.calcite.rel.externalize.RelWriterImpl; |
23 | 24 | import org.apache.calcite.rel.rules.CoreRules; |
24 | 25 | import org.apache.calcite.rel.type.RelDataTypeFactory; |
| 26 | +import org.apache.calcite.rex.RexBuilder; |
| 27 | +import org.apache.calcite.rex.RexNode; |
25 | 28 | import org.apache.calcite.sql.SqlExplainLevel; |
26 | 29 | import org.apache.calcite.sql.SqlNode; |
| 30 | +import org.apache.calcite.sql.fun.SqlStdOperatorTable; |
27 | 31 | import org.apache.calcite.sql.parser.SqlParseException; |
28 | 32 | import org.apache.calcite.sql.type.SqlTypeName; |
29 | 33 | import org.apache.calcite.tools.RuleSet; |
30 | 34 | import org.apache.calcite.tools.RuleSets; |
31 | 35 |
|
32 | 36 | import org.apache.wayang.api.sql.calcite.convention.WayangConvention; |
| 37 | +import org.apache.wayang.api.sql.calcite.converter.functions.FilterPredicateImpl; |
33 | 38 | import org.apache.wayang.api.sql.calcite.optimizer.Optimizer; |
34 | 39 | import org.apache.wayang.api.sql.calcite.rules.WayangRules; |
35 | 40 | import org.apache.wayang.api.sql.calcite.schema.SchemaUtils; |
|
41 | 46 | import org.apache.wayang.api.sql.context.SqlContext; |
42 | 47 | import org.apache.wayang.basic.data.Tuple2; |
43 | 48 | import org.apache.wayang.core.api.Configuration; |
| 49 | +import org.apache.wayang.core.function.FunctionDescriptor.SerializableFunction; |
| 50 | +import org.apache.wayang.core.function.FunctionDescriptor.SerializablePredicate; |
44 | 51 | import org.apache.wayang.core.plan.wayangplan.Operator; |
45 | 52 | import org.apache.wayang.core.plan.wayangplan.PlanTraversal; |
46 | 53 | import org.apache.wayang.core.plan.wayangplan.WayangPlan; |
47 | 54 | import org.apache.wayang.java.Java; |
| 55 | +import org.apache.wayang.spark.Spark; |
48 | 56 | import org.apache.wayang.basic.data.Record; |
49 | 57 | import org.json.simple.JSONObject; |
50 | 58 | import org.json.simple.parser.JSONParser; |
51 | 59 | import org.json.simple.parser.ParseException; |
52 | 60 |
|
53 | 61 | import org.junit.Test; |
54 | 62 |
|
| 63 | +import java.io.ByteArrayInputStream; |
| 64 | +import java.io.ByteArrayOutputStream; |
55 | 65 | import java.io.IOException; |
| 66 | +import java.io.ObjectInputStream; |
| 67 | +import java.io.ObjectOutputStream; |
56 | 68 | import java.io.PrintWriter; |
57 | 69 | import java.io.StringWriter; |
58 | 70 | import java.sql.SQLException; |
@@ -371,6 +383,62 @@ public void joinWithLargeLeftTableIndexMirrorAlias() throws Exception { |
371 | 383 | assert (resultTally.equals(shouldBeTally)); |
372 | 384 | } |
373 | 385 |
|
| 386 | + // tests sql-apis ability to serialize projections and joins |
| 387 | + @Test |
| 388 | + public void sparkInnerJoin() throws Exception { |
| 389 | + final SqlContext sqlContext = createSqlContext("/data/largeLeftTableIndex.csv"); |
| 390 | + |
| 391 | + final Tuple2<Collection<Record>, WayangPlan> t = this.buildCollectorAndWayangPlan(sqlContext, |
| 392 | + "SELECT * FROM fs.largeLeftTableIndex AS na INNER JOIN fs.largeLeftTableIndex AS nb ON nb.NAMEB = na.NAMEA " // |
| 393 | + ); |
| 394 | + |
| 395 | + final Collection<Record> result = t.field0; |
| 396 | + final WayangPlan wayangPlan = t.field1; |
| 397 | + |
| 398 | + PlanTraversal.upstream().traverse(wayangPlan.getSinks()).getTraversedNodes().forEach(node -> { |
| 399 | + node.addTargetPlatform(Spark.platform()); |
| 400 | + }); |
| 401 | + |
| 402 | + sqlContext.execute(wayangPlan); |
| 403 | + |
| 404 | + final List<Record> shouldBe = List.of( |
| 405 | + new Record("test1", "test1", "test2", "test1", "test1", "test2"), |
| 406 | + new Record("test2", "" , "test2", "" , "test2", "test2"), |
| 407 | + new Record("" , "test2", "test2", "test2", "" , "test2") |
| 408 | + ); |
| 409 | + |
| 410 | + final Map<Record, Integer> resultTally = result.stream() |
| 411 | + .collect(Collectors.toMap(rec -> rec, rec -> 1, Integer::sum)); |
| 412 | + final Map<Record, Integer> shouldBeTally = shouldBe.stream() |
| 413 | + .collect(Collectors.toMap(rec -> rec, rec -> 1, Integer::sum)); |
| 414 | + |
| 415 | + assert (resultTally.equals(shouldBeTally)); |
| 416 | + } |
| 417 | + |
| 418 | + //@Test |
| 419 | + public void rexSerializationTest() throws Exception { |
| 420 | + // create filterPredicateImpl for serialisation |
| 421 | + final RelDataTypeFactory typeFactory = new JavaTypeFactoryImpl(); |
| 422 | + final RexBuilder rb = new RexBuilder(typeFactory); |
| 423 | + final RexNode leftOperand = rb.makeInputRef(typeFactory.createSqlType(SqlTypeName.VARCHAR), 0); |
| 424 | + final RexNode rightOperand = rb.makeLiteral("test"); |
| 425 | + final RexNode cond = rb.makeCall(SqlStdOperatorTable.EQUALS, leftOperand, rightOperand); |
| 426 | + final SerializablePredicate<?> fpImpl = new FilterPredicateImpl(cond); |
| 427 | + |
| 428 | + final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| 429 | + final ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); |
| 430 | + objectOutputStream.writeObject(fpImpl); |
| 431 | + objectOutputStream.close(); |
| 432 | + |
| 433 | + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( |
| 434 | + byteArrayOutputStream.toByteArray()); |
| 435 | + final ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); |
| 436 | + final Object deserializedObject = objectInputStream.readObject(); |
| 437 | + objectInputStream.close(); |
| 438 | + |
| 439 | + assert (((FilterPredicateImpl) deserializedObject).test(new Record("test"))); |
| 440 | + } |
| 441 | + |
374 | 442 | @Test |
375 | 443 | public void exampleFilterTableRefToTableRef() throws Exception { |
376 | 444 | final SqlContext sqlContext = createSqlContext("/data/exampleRefToRef.csv"); |
|
0 commit comments