> labels = new ArrayList<>();
290 | result.stream().iterator().forEachRemaining(map -> map.forEach((key, value) -> {
291 | labels.add(new Pair<>(map.get("in").toString(), map.get("out").toString()));
292 | }));
293 | LOGGER.debug(String.format("End %s%n", query));
294 | return labels;
295 | }
296 | }
297 | }
298 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/calcite/GremlinFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.calcite;
21 |
22 | import org.apache.calcite.plan.RelOptCluster;
23 | import org.apache.calcite.plan.RelTraitSet;
24 | import org.apache.calcite.rel.RelNode;
25 | import org.apache.calcite.rel.core.Filter;
26 | import org.apache.calcite.rex.RexNode;
27 |
28 | /**
29 | * @author Lyndon Bauto (lyndonb@bitquilltech.com)
30 | * @author Adapted from implementation by twilmes (https://github.com/twilmes/sql-gremlin)
31 | *
32 | *
33 | */
34 | public class GremlinFilter extends Filter implements GremlinRel {
35 | public GremlinFilter(
36 | final RelOptCluster cluster,
37 | final RelTraitSet traitSet,
38 | final RelNode child,
39 | final RexNode condition) {
40 | super(cluster, traitSet, child, condition);
41 | }
42 |
43 | @Override
44 | public Filter copy(final RelTraitSet traitSet, final RelNode input, final RexNode condition) {
45 | return new GremlinFilter(getCluster(), traitSet, input, condition);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/calcite/GremlinRel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.calcite;
21 |
22 | import org.apache.calcite.plan.Convention;
23 | import org.apache.calcite.rel.RelNode;
24 |
25 | /**
26 | * Created by twilmes on 9/25/15.
27 | * Modified by lyndonb-bq on 05/17/21.
28 | */
29 | public interface GremlinRel extends RelNode {
30 | /**
31 | * Calling convention for relational operations that occur in Gremlin.
32 | */
33 | Convention CONVENTION = new Convention.Impl("GREMLIN", GremlinRel.class);
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/calcite/GremlinRules.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.calcite;
21 |
22 | import org.apache.calcite.plan.Convention;
23 | import org.apache.calcite.plan.RelOptRule;
24 | import org.apache.calcite.plan.RelTrait;
25 | import org.apache.calcite.plan.RelTraitSet;
26 | import org.apache.calcite.rel.RelNode;
27 | import org.apache.calcite.rel.convert.ConverterRule;
28 | import org.apache.calcite.rel.logical.LogicalFilter;
29 |
30 | /**
31 | * List of rules that get pushed down and converted into GremlinTraversals. Right now
32 | * only filter is pushed down using rules. Joins are converted, but handled the by RelWalker
33 | * utilities.
34 | *
35 | * Created by twilmes on 11/14/15.
36 | * Modified by lyndonb-bq on 05/17/21.
37 | */
38 | public class GremlinRules {
39 | public static final RelOptRule[] RULES = {
40 | GremlinFilterRule.INSTANCE
41 | };
42 |
43 | abstract static class GremlinConverterRule extends ConverterRule {
44 | private final Convention out;
45 |
46 | GremlinConverterRule(
47 | final Class extends RelNode> clazz,
48 | final RelTrait in,
49 | final Convention out,
50 | final String description) {
51 | super(clazz, in, out, description);
52 | this.out = out;
53 | }
54 |
55 | protected Convention getOut() {
56 | return out;
57 | }
58 | }
59 |
60 | private static final class GremlinFilterRule extends GremlinConverterRule {
61 | private static final GremlinFilterRule INSTANCE = new GremlinFilterRule();
62 |
63 | private GremlinFilterRule() {
64 | super(LogicalFilter.class, Convention.NONE, GremlinRel.CONVENTION, "GremlinFilterRule");
65 | }
66 |
67 | public RelNode convert(final RelNode rel) {
68 | final LogicalFilter filter = (LogicalFilter) rel;
69 | final RelTraitSet traitSet = filter.getTraitSet().replace(getOut());
70 | return new GremlinFilter(rel.getCluster(), traitSet, convert(filter.getInput(), getOut()),
71 | filter.getCondition());
72 | }
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/calcite/GremlinSchema.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.calcite;
21 |
22 | import com.google.common.collect.ImmutableMap;
23 | import lombok.AllArgsConstructor;
24 | import org.apache.calcite.schema.Table;
25 | import org.apache.calcite.schema.impl.AbstractSchema;
26 | import org.twilmes.sql.gremlin.adapter.converter.schema.gremlin.GremlinEdgeTable;
27 | import org.twilmes.sql.gremlin.adapter.converter.schema.gremlin.GremlinTableBase;
28 | import org.twilmes.sql.gremlin.adapter.converter.schema.gremlin.GremlinVertexTable;
29 | import java.util.ArrayList;
30 | import java.util.List;
31 | import java.util.Map;
32 | import java.util.stream.Collectors;
33 |
34 | /**
35 | * Created by twilmes on 9/22/15.
36 | * Modified by lyndonb-bq on 05/17/21.
37 | */
38 | @AllArgsConstructor
39 | public class GremlinSchema extends AbstractSchema {
40 | private final List vertices;
41 | private final List edges;
42 |
43 | @Override
44 | protected Map getTableMap() {
45 | final ImmutableMap.Builder builder = ImmutableMap.builder();
46 | builder.putAll(vertices.stream().collect(Collectors.toMap(GremlinTableBase::getLabel, t -> t)));
47 | builder.putAll(edges.stream().collect(Collectors.toMap(GremlinTableBase::getLabel, t -> t)));
48 | final Map tableMap = builder.build();
49 | return tableMap;
50 | }
51 |
52 | public List getVertices() {
53 | return new ArrayList<>(vertices);
54 | }
55 |
56 | public List getEdges() {
57 | return new ArrayList<>(edges);
58 | }
59 |
60 | public List getAllTables() {
61 | final List gremlinTableBases = new ArrayList<>();
62 | gremlinTableBases.addAll(vertices);
63 | gremlinTableBases.addAll(edges);
64 | return gremlinTableBases;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/calcite/GremlinTableScan.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.calcite;
21 |
22 | import org.apache.calcite.plan.RelOptCluster;
23 | import org.apache.calcite.plan.RelOptPlanner;
24 | import org.apache.calcite.plan.RelOptRule;
25 | import org.apache.calcite.plan.RelOptTable;
26 | import org.apache.calcite.plan.RelTraitSet;
27 | import org.apache.calcite.rel.RelNode;
28 | import org.apache.calcite.rel.core.TableScan;
29 | import org.apache.calcite.rel.type.RelDataType;
30 | import org.apache.calcite.rel.type.RelDataTypeFactory;
31 | import org.apache.calcite.rel.type.RelDataTypeField;
32 | import java.util.List;
33 |
34 | /**
35 | * Created by twilmes on 9/25/15.
36 | * Modified by lyndonb-bq on 05/17/21.
37 | */
38 | public class GremlinTableScan extends TableScan implements GremlinRel {
39 | /**
40 | * Calling convention for relational operations that occur in Gremlin.
41 | */
42 | private final int[] fields;
43 |
44 | public GremlinTableScan(final RelOptCluster cluster, final RelTraitSet traitSet,
45 | final RelOptTable table, final int[] fields) {
46 | super(cluster, traitSet, table);
47 | this.fields = fields;
48 | }
49 |
50 | @Override
51 | public RelNode copy(final RelTraitSet traitSet, final List inputs) {
52 | assert inputs.isEmpty();
53 | return this;
54 | }
55 |
56 | @Override
57 | public RelDataType deriveRowType() {
58 | final List fieldList = table.getRowType().getFieldList();
59 | final RelDataTypeFactory.FieldInfoBuilder builder =
60 | getCluster().getTypeFactory().builder();
61 | for (final int field : fields) {
62 | builder.add(fieldList.get(field));
63 | }
64 | return builder.build();
65 | }
66 |
67 | @Override
68 | public void register(final RelOptPlanner planner) {
69 | planner.addRule(GremlinToEnumerableConverterRule.INSTANCE);
70 | for (final RelOptRule rule : GremlinRules.RULES) {
71 | planner.addRule(rule);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/calcite/GremlinToEnumerableConverter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.calcite;
21 |
22 | import org.apache.calcite.adapter.enumerable.EnumerableRel;
23 | import org.apache.calcite.adapter.enumerable.EnumerableRelImplementor;
24 | import org.apache.calcite.plan.ConventionTraitDef;
25 | import org.apache.calcite.plan.RelOptCluster;
26 | import org.apache.calcite.plan.RelTraitSet;
27 | import org.apache.calcite.rel.RelNode;
28 | import org.apache.calcite.rel.convert.ConverterImpl;
29 | import java.util.List;
30 |
31 | /**
32 | * Created by twilmes on 9/25/15.
33 | * Modified by lyndonb-bq on 05/17/21.
34 | * Relational expression representing a scan of a table in a TinkerPop data source.
35 | */
36 | public class GremlinToEnumerableConverter
37 | extends ConverterImpl
38 | implements EnumerableRel {
39 | protected GremlinToEnumerableConverter(
40 | final RelOptCluster cluster,
41 | final RelTraitSet traits,
42 | final RelNode input) {
43 | super(cluster, ConventionTraitDef.INSTANCE, traits, input);
44 | }
45 |
46 | @Override
47 | public RelNode copy(final RelTraitSet traitSet, final List inputs) {
48 | return new GremlinToEnumerableConverter(
49 | getCluster(), traitSet, sole(inputs));
50 | }
51 |
52 | @Override
53 | public Result implement(final EnumerableRelImplementor implementor, final Prefer pref) {
54 | return null;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/calcite/GremlinToEnumerableConverterRule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.calcite;
21 |
22 | /**
23 | * Created by twilmes on 9/25/15.
24 | * Modified by lyndonb-bq on 05/17/21.
25 | */
26 |
27 | import org.apache.calcite.adapter.enumerable.EnumerableConvention;
28 | import org.apache.calcite.plan.RelTraitSet;
29 | import org.apache.calcite.rel.RelNode;
30 | import org.apache.calcite.rel.convert.ConverterRule;
31 |
32 | /**
33 | * Rule to convert a relational expression from
34 | * {@link GremlinRel#CONVENTION} to {@link org.apache.calcite.adapter.enumerable.EnumerableConvention}.
35 | */
36 | public final class GremlinToEnumerableConverterRule extends ConverterRule {
37 | public static final ConverterRule INSTANCE =
38 | new GremlinToEnumerableConverterRule();
39 |
40 | private GremlinToEnumerableConverterRule() {
41 | super(RelNode.class, GremlinRel.CONVENTION, EnumerableConvention.INSTANCE,"GremlinToEnumerableConverterRule");
42 | }
43 |
44 | @Override
45 | public RelNode convert(final RelNode rel) {
46 | final RelTraitSet newTraitSet = rel.getTraitSet().replace(getOutConvention());
47 | return new GremlinToEnumerableConverter(rel.getCluster(), newTraitSet, rel);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/gremlin/GremlinEdgeTable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.gremlin;
21 |
22 | import lombok.Getter;
23 | import org.apache.calcite.util.Pair;
24 | import java.util.List;
25 | import java.util.Map;
26 | import java.util.stream.Collectors;
27 |
28 | /**
29 | * Created by twilmes on 10/10/15.
30 | * Modified by lyndonb-bq on 05/17/21.
31 | */
32 | @Getter
33 | public class GremlinEdgeTable extends GremlinTableBase {
34 | private final List> inOutVertexPairs;
35 |
36 | public GremlinEdgeTable(final String label, final List columns,
37 | final List> inOutVertexPairs) {
38 | super(label, false, convert(label, columns, inOutVertexPairs));
39 | this.inOutVertexPairs = inOutVertexPairs;
40 | }
41 |
42 | private static Map convert(
43 | final String label, final List columns,
44 | final List> inOutTablePairs) {
45 | final Map columnsWithPKFK =
46 | columns.stream().collect(Collectors.toMap(GremlinProperty::getName, t -> t));
47 |
48 | // Uppercase edge label appended with '_ID' represents an edge, this is a string type.
49 | final GremlinProperty pk = new GremlinProperty(label + GremlinTableBase.ID, "string");
50 | columnsWithPKFK.put(pk.getName(), pk);
51 |
52 | // Get in and out foreign keys of edge.
53 | inOutTablePairs.forEach(inOutPair -> {
54 | // Uppercase vertex label appended with 'IN_ID'/'OUT_ID' represents a connected vertex, this is a string type.
55 | final GremlinProperty inFk = new GremlinProperty(inOutPair.getKey() + GremlinTableBase.IN_ID, "string");
56 | final GremlinProperty outFk = new GremlinProperty(inOutPair.getValue() + GremlinTableBase.OUT_ID, "string");
57 | columnsWithPKFK.put(inFk.getName(), inFk);
58 | columnsWithPKFK.put(outFk.getName(), inFk);
59 | });
60 | return columnsWithPKFK;
61 | }
62 |
63 | public boolean isEdgeBetween(final String in, final String out) {
64 | for (final Pair inOutPair : inOutVertexPairs) {
65 | if (inOutPair.getKey().equalsIgnoreCase(in + GremlinTableBase.IN_ID)
66 | && inOutPair.getValue().equalsIgnoreCase(out + GremlinTableBase.OUT_ID)) {
67 | return true;
68 | }
69 | }
70 | return false;
71 | }
72 |
73 | public boolean hasInVertex(final String inVertexLabel) {
74 | final String label = inVertexLabel.replace(IN_ID, "");
75 | for (final Pair pair : inOutVertexPairs) {
76 | if (pair.getKey().equalsIgnoreCase(label)) {
77 | return true;
78 | }
79 | }
80 | return false;
81 | }
82 |
83 | public boolean hasOutVertex(final String outVertexLabel) {
84 | final String label = outVertexLabel.replace(IN_ID, "");
85 | for (final Pair pair : inOutVertexPairs) {
86 | if (pair.getValue().equalsIgnoreCase(label)) {
87 | return true;
88 | }
89 | }
90 | return false;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/gremlin/GremlinProperty.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.gremlin;
21 |
22 | import lombok.AllArgsConstructor;
23 | import lombok.Getter;
24 |
25 | /**
26 | * Created by twilmes on 10/10/15.
27 | * Modified by lyndonb-bq on 05/17/21.
28 | */
29 | @Getter
30 | @AllArgsConstructor
31 | public class GremlinProperty {
32 | private final String name;
33 | private final String type;
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/gremlin/GremlinTableBase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.gremlin;
21 |
22 | import lombok.Getter;
23 | import org.apache.calcite.adapter.java.AbstractQueryableTable;
24 | import org.apache.calcite.linq4j.QueryProvider;
25 | import org.apache.calcite.linq4j.Queryable;
26 | import org.apache.calcite.plan.RelOptTable;
27 | import org.apache.calcite.rel.RelNode;
28 | import org.apache.calcite.rel.type.RelDataType;
29 | import org.apache.calcite.rel.type.RelDataTypeFactory;
30 | import org.apache.calcite.schema.SchemaPlus;
31 | import org.apache.calcite.schema.TranslatableTable;
32 | import org.apache.calcite.util.Pair;
33 | import org.twilmes.sql.gremlin.adapter.converter.schema.calcite.GremlinRel;
34 | import org.twilmes.sql.gremlin.adapter.converter.schema.calcite.GremlinTableScan;
35 | import java.sql.SQLException;
36 | import java.util.ArrayList;
37 | import java.util.List;
38 | import java.util.Map;
39 |
40 | @Getter
41 | public class GremlinTableBase extends AbstractQueryableTable implements TranslatableTable {
42 | private final String label;
43 | private final Boolean isVertex;
44 | private final Map columns;
45 | public static final String ID = "_ID";
46 | public static final String IN_ID = "_IN" + ID;
47 | public static final String OUT_ID = "_OUT" + ID;
48 |
49 | public GremlinTableBase(final String label, final Boolean isVertex,
50 | final Map columns) {
51 | super(Object[].class);
52 | this.label = label;
53 | this.isVertex = isVertex;
54 | this.columns = columns;
55 | }
56 |
57 | public GremlinProperty getColumn(final String column) throws SQLException {
58 | for (final String key : columns.keySet()) {
59 | if (key.equalsIgnoreCase(column)) {
60 | return columns.get(key);
61 | }
62 | }
63 | throw new SQLException(String.format(
64 | "Error: Could not find column '%s' on %s with label '%s'.", column, isVertex ? "vertex" : "edge", label));
65 | }
66 |
67 | @Override
68 | public Queryable asQueryable(final QueryProvider queryProvider, final SchemaPlus schema, final String tableName) {
69 | return null;
70 | }
71 |
72 | @Override
73 | public RelNode toRel(final RelOptTable.ToRelContext context, final RelOptTable relOptTable) {
74 | final int[] fields = new int[columns.size()];
75 | for (int i = 0; i < fields.length; i++) {
76 | fields[i] = i;
77 | }
78 | return new GremlinTableScan(context.getCluster(), context.getCluster().traitSetOf(GremlinRel.CONVENTION), relOptTable, fields);
79 | }
80 |
81 | @Override
82 | public RelDataType getRowType(final RelDataTypeFactory relDataTypeFactory) {
83 | final List names = new ArrayList<>();
84 | final List types = new ArrayList<>();
85 | for (final Map.Entry entry : columns.entrySet()) {
86 | names.add(entry.getKey());
87 | types.add(relDataTypeFactory.createJavaType(getType(entry.getValue().getType())));
88 | }
89 | return relDataTypeFactory.createStructType(Pair.zip(names, types));
90 | }
91 |
92 | private Class> getType(final String className) {
93 | if ("string".equalsIgnoreCase(className)) {
94 | return String.class;
95 | } else if ("integer".equalsIgnoreCase(className)) {
96 | return Integer.class;
97 | } else if ("float".equalsIgnoreCase(className)) {
98 | return Float.class;
99 | } else if ("byte".equalsIgnoreCase(className)) {
100 | return Byte.class;
101 | } else if ("short".equalsIgnoreCase(className)) {
102 | return Short.class;
103 | } else if ("double".equalsIgnoreCase(className)) {
104 | return Double.class;
105 | } else if ("long".equalsIgnoreCase(className)) {
106 | return Long.class;
107 | } else if ("boolean".equalsIgnoreCase(className)) {
108 | return Boolean.class;
109 | } else if ("date".equalsIgnoreCase(className) || "long_date".equalsIgnoreCase(className)) {
110 | return java.sql.Date.class;
111 | } else if ("timestamp".equalsIgnoreCase(className) || "long_timestamp".equalsIgnoreCase(className)) {
112 | return java.sql.Timestamp.class;
113 | } else {
114 | return null;
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/converter/schema/gremlin/GremlinVertexTable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.converter.schema.gremlin;
21 |
22 | import lombok.Getter;
23 | import java.util.List;
24 | import java.util.Map;
25 | import java.util.stream.Collectors;
26 |
27 | @Getter
28 | public class GremlinVertexTable extends GremlinTableBase {
29 | private final List inEdges;
30 | private final List outEdges;
31 |
32 | public GremlinVertexTable(final String label, final List columns, final List inEdges, final List outEdges) {
33 | super(label, true, convert(label, columns, inEdges, outEdges));
34 | this.inEdges = inEdges;
35 | this.outEdges = outEdges;
36 | }
37 |
38 | // String for edges because 1 vertex can be connected to many edges (may required representation like '[1, 2, 3]"
39 | // Long type for vertices because an edge can only be connected to one vertex (on each side).
40 | private static Map convert(
41 | final String label, final List columns,
42 | final List inEdges, final List outEdges) {
43 | final Map columnsWithPKFK =
44 | columns.stream().collect(Collectors.toMap(GremlinProperty::getName, t -> t));
45 |
46 | // Uppercase vertex label appended with '_ID' represents an vertex, this is a string type.
47 | final GremlinProperty pk = new GremlinProperty(label + ID, "string");
48 | columnsWithPKFK.put(pk.getName(), pk);
49 |
50 | // Get in and out foreign keys of edge.
51 | inEdges.forEach(inEdgeLabel -> {
52 | // Uppercase edge label appended with 'IN_ID'/'OUT_ID' represents a connected edge, this is a string type.
53 | final GremlinProperty inFk = new GremlinProperty(inEdgeLabel + IN_ID, "string");
54 | columnsWithPKFK.put(inFk.getName(), inFk);
55 | });
56 | outEdges.forEach(outEdgeLabel -> {
57 | // Uppercase edge label appended with 'IN_ID'/'OUT_ID' represents a connected edge, this is a string type.
58 | final GremlinProperty inFk = new GremlinProperty(outEdgeLabel + OUT_ID, "string");
59 | columnsWithPKFK.put(inFk.getName(), inFk);
60 | });
61 | return columnsWithPKFK;
62 | }
63 |
64 | public boolean hasInEdge(final String label) {
65 | return inEdges.stream().anyMatch(e -> e.equalsIgnoreCase(label.replace(IN_ID, "")));
66 | }
67 |
68 | public boolean hasOutEdge(final String label) {
69 | return outEdges.stream().anyMatch(e -> e.equalsIgnoreCase(label.replace(OUT_ID, "")));
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/org/twilmes/sql/gremlin/adapter/results/SqlGremlinQueryResult.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package org.twilmes.sql.gremlin.adapter.results;
21 |
22 | import lombok.Getter;
23 | import org.twilmes.sql.gremlin.adapter.converter.SqlMetadata;
24 | import org.twilmes.sql.gremlin.adapter.converter.schema.gremlin.GremlinProperty;
25 | import org.twilmes.sql.gremlin.adapter.converter.schema.gremlin.GremlinTableBase;
26 | import java.sql.SQLException;
27 | import java.util.ArrayList;
28 | import java.util.List;
29 | import java.util.concurrent.BlockingQueue;
30 | import java.util.concurrent.LinkedBlockingQueue;
31 |
32 | @Getter
33 | public class SqlGremlinQueryResult {
34 | public static final String EMPTY_MESSAGE = "No more results.";
35 | public static final String NULL_VALUE = "$%#NULL#%$";
36 | private final List columns;
37 | private final List columnTypes = new ArrayList<>();
38 | private final Object assertEmptyLock = new Object();
39 | private final BlockingQueue> blockingQueueRows = new LinkedBlockingQueue<>();
40 | private boolean isEmpty = false;
41 | private SQLException paginationException = null;
42 | private Thread currThread = null;
43 |
44 | public SqlGremlinQueryResult(final List columns, final List gremlinTableBases,
45 | final SqlMetadata sqlMetadata) throws SQLException {
46 | this.columns = columns;
47 | for (final String column : columns) {
48 | GremlinProperty col = null;
49 | for (final GremlinTableBase gremlinTableBase : gremlinTableBases) {
50 | if (sqlMetadata.getTableHasColumn(gremlinTableBase, column)) {
51 | col = sqlMetadata.getGremlinProperty(gremlinTableBase.getLabel(), column);
52 | break;
53 | }
54 | }
55 | columnTypes.add((col == null || col.getType() == null) ? "string" : col.getType());
56 | }
57 | }
58 |
59 | public void setPaginationException(final SQLException e) {
60 | synchronized (assertEmptyLock) {
61 | paginationException = e;
62 | if (currThread != null && blockingQueueRows.size() == 0) {
63 | currThread.interrupt();
64 | }
65 | }
66 | }
67 |
68 | public boolean getIsEmpty() throws SQLException {
69 | if (paginationException == null) {
70 | return isEmpty;
71 | }
72 | throw paginationException;
73 | }
74 |
75 | public void assertIsEmpty() {
76 | synchronized (assertEmptyLock) {
77 | if (currThread != null && blockingQueueRows.size() == 0) {
78 | currThread.interrupt();
79 | }
80 | isEmpty = true;
81 | }
82 | }
83 |
84 | public void addResults(final List> rows) {
85 | for (final List