You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2020/01/09 11:48:03 UTC

[tinkerpop] 08/13: Created a JDBCQueryStrategy that looks for 'join' semantics in the bytecode and folds it into a custom jdbs:sql instruction that does a SELECT call.

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch 4.0-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 7142dc16d8fc81ad8bd4090096b42e5b9b1744f4
Author: Marko A. Rodriguez <ok...@gmail.com>
AuthorDate: Mon Apr 29 13:56:21 2019 -0600

    Created a JDBCQueryStrategy that looks for 'join' semantics in the bytecode and folds it into a custom jdbs:sql instruction that does a SELECT call.
---
 .../tinkerpop/machine/bytecode/Bytecode.java       |   5 +
 .../tinkerpop/machine/bytecode/BytecodeUtil.java   |  12 +++
 .../bytecode/compiler/BytecodeCompiler.java        |   3 +-
 .../machine/bytecode/compiler/Compilation.java     |   4 +-
 .../bytecode/compiler/SourceCompilation.java       |   4 +-
 .../machine/function/barrier/OrderBarrier.java     |   2 +-
 .../machine/function/branch/RepeatBranch.java      |   4 +-
 .../machine/function/initial/FlatMapInitial.java   |   9 +-
 .../processor/{ => util}/EmptyProcessor.java       |   5 +-
 .../processor/{ => util}/FilterProcessor.java      |   2 +-
 .../processor/{ => util}/LoopsProcessor.java       |   2 +-
 .../processor/{ => util}/SimpleProcessor.java      |   4 +-
 .../tinkerpop/machine/structure/TSymbol.java       |  26 -----
 .../machine/structure/graph/IdSymbol.java          |  52 ----------
 .../machine/structure/graph/LabelSymbol.java       |  52 ----------
 .../tinkerpop/machine/structure/graph/TGraph.java  |   4 +-
 .../machine/structure/graph/TVertices.java         |  27 ------
 .../structure/{ => util}/EmptyStructure.java       |   5 +-
 .../tinkerpop/machine/structure/util/JTuple.java   |   5 +
 .../structure/{graph/G.java => util/TSymbol.java}  |  22 +++--
 .../machine/traverser/path/BasicPath.java          |   1 +
 .../machine/structure/jdbc/JDBCDatabase.java       |   6 +-
 .../machine/structure/jdbc/JDBCStructure.java      |  11 ++-
 .../jdbc/bytecode/compiler/JDBCCompiler.java       |  69 ++++++++++++++
 .../jdbc/function/flatmap/SqlFlatMap.java          | 105 +++++++++++++++++++++
 .../structure/jdbc/strategy/JDBCQueryStrategy.java |  55 +++++++++++
 .../structure/jdbc/strategy/JDBCStrategy.java      |   7 ++
 .../tinkerpop/machine/structure/jdbc/JDBCTest.java |   8 +-
 28 files changed, 324 insertions(+), 187 deletions(-)

diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/Bytecode.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/Bytecode.java
index eeeeacc..7519652 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/Bytecode.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/Bytecode.java
@@ -64,6 +64,11 @@ public final class Bytecode<C> implements Cloneable, Serializable {
         this.instructions.add(new Instruction<>(coefficient, op, args));
     }
 
+    public void addInstruction(final int index, final Coefficient<C> coefficient, final String op, final Object... args) {
+        BytecodeUtil.linkBytecodeChildren(this, args);
+        this.instructions.add(index, new Instruction<>(coefficient, op, args));
+    }
+
     public List<Instruction<C>> getInstructions() {
         return this.instructions;
     }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java
index c4ea488..afb3072 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java
@@ -187,4 +187,16 @@ public final class BytecodeUtil {
         }
         return Optional.of(COP_TraverserFactory.instance());
     }
+
+    public static <C> boolean startsWith(final Bytecode<C> bytecode, String... ops) {
+        int i = 0;
+        for (final Instruction<C> instruction : bytecode.getInstructions()) {
+            if (!instruction.op().equals(ops[i]))
+                return false;
+            i++;
+            if (i >= ops.length)
+                return true;
+        }
+        return false;
+    }
 }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/BytecodeCompiler.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/BytecodeCompiler.java
index 16cf912..07b49ed 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/BytecodeCompiler.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/BytecodeCompiler.java
@@ -19,6 +19,7 @@
 package org.apache.tinkerpop.machine.bytecode.compiler;
 
 import org.apache.tinkerpop.machine.bytecode.Bytecode;
+import org.apache.tinkerpop.machine.bytecode.BytecodeUtil;
 import org.apache.tinkerpop.machine.bytecode.Instruction;
 import org.apache.tinkerpop.machine.function.CFunction;
 import org.apache.tinkerpop.machine.function.initial.FlatMapInitial;
@@ -37,7 +38,7 @@ public interface BytecodeCompiler {
         for (final Instruction<C> instruction : bytecode.getInstructions()) {
             final CFunction function = this.compile(instruction);
             functions.add(functions.isEmpty() && bytecode.getParent().isEmpty() && function instanceof Initializing ?
-                    new FlatMapInitial<>(function.coefficient(), function.label(), (Initializing) function) : function);
+                    new FlatMapInitial<>(function.coefficient(), function.label(), (Initializing) function, BytecodeUtil.getTraverserFactory(bytecode).get()) : function);
         }
         return functions;
     }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Compilation.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Compilation.java
index f7105d9..b7370ff 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Compilation.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Compilation.java
@@ -21,10 +21,10 @@ package org.apache.tinkerpop.machine.bytecode.compiler;
 import org.apache.tinkerpop.machine.bytecode.Bytecode;
 import org.apache.tinkerpop.machine.bytecode.BytecodeUtil;
 import org.apache.tinkerpop.machine.function.CFunction;
-import org.apache.tinkerpop.machine.processor.EmptyProcessor;
+import org.apache.tinkerpop.machine.processor.util.EmptyProcessor;
 import org.apache.tinkerpop.machine.processor.Processor;
 import org.apache.tinkerpop.machine.processor.ProcessorFactory;
-import org.apache.tinkerpop.machine.structure.EmptyStructure;
+import org.apache.tinkerpop.machine.structure.util.EmptyStructure;
 import org.apache.tinkerpop.machine.structure.StructureFactory;
 import org.apache.tinkerpop.machine.traverser.Traverser;
 import org.apache.tinkerpop.machine.traverser.TraverserFactory;
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/SourceCompilation.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/SourceCompilation.java
index 70a9603..9feeb59 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/SourceCompilation.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/SourceCompilation.java
@@ -20,10 +20,10 @@ package org.apache.tinkerpop.machine.bytecode.compiler;
 
 import org.apache.tinkerpop.machine.bytecode.Bytecode;
 import org.apache.tinkerpop.machine.bytecode.BytecodeUtil;
-import org.apache.tinkerpop.machine.processor.EmptyProcessor;
+import org.apache.tinkerpop.machine.processor.util.EmptyProcessor;
 import org.apache.tinkerpop.machine.processor.ProcessorFactory;
 import org.apache.tinkerpop.machine.strategy.Strategy;
-import org.apache.tinkerpop.machine.structure.EmptyStructure;
+import org.apache.tinkerpop.machine.structure.util.EmptyStructure;
 import org.apache.tinkerpop.machine.structure.StructureFactory;
 
 import java.util.Set;
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/barrier/OrderBarrier.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/barrier/OrderBarrier.java
index ed81393..05f02e2 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/barrier/OrderBarrier.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/barrier/OrderBarrier.java
@@ -25,7 +25,7 @@ import org.apache.tinkerpop.machine.bytecode.compiler.Order;
 import org.apache.tinkerpop.machine.coefficient.Coefficient;
 import org.apache.tinkerpop.machine.function.AbstractFunction;
 import org.apache.tinkerpop.machine.function.BarrierFunction;
-import org.apache.tinkerpop.machine.processor.FilterProcessor;
+import org.apache.tinkerpop.machine.processor.util.FilterProcessor;
 import org.apache.tinkerpop.machine.traverser.Traverser;
 import org.apache.tinkerpop.machine.traverser.TraverserSet;
 import org.apache.tinkerpop.machine.traverser.species.ProjectedTraverser;
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/RepeatBranch.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/RepeatBranch.java
index 378eb6d..8d73d5f 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/RepeatBranch.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/RepeatBranch.java
@@ -23,8 +23,8 @@ import org.apache.tinkerpop.machine.bytecode.Instruction;
 import org.apache.tinkerpop.machine.bytecode.compiler.Compilation;
 import org.apache.tinkerpop.machine.coefficient.Coefficient;
 import org.apache.tinkerpop.machine.function.AbstractFunction;
-import org.apache.tinkerpop.machine.processor.FilterProcessor;
-import org.apache.tinkerpop.machine.processor.LoopsProcessor;
+import org.apache.tinkerpop.machine.processor.util.FilterProcessor;
+import org.apache.tinkerpop.machine.processor.util.LoopsProcessor;
 import org.apache.tinkerpop.machine.util.StringFactory;
 
 import java.util.ArrayList;
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/FlatMapInitial.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/FlatMapInitial.java
index 2a2ca21..8b06567 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/FlatMapInitial.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/FlatMapInitial.java
@@ -21,7 +21,7 @@ package org.apache.tinkerpop.machine.function.initial;
 import org.apache.tinkerpop.machine.coefficient.Coefficient;
 import org.apache.tinkerpop.machine.function.AbstractFunction;
 import org.apache.tinkerpop.machine.function.InitialFunction;
-import org.apache.tinkerpop.machine.traverser.species.EmptyTraverser;
+import org.apache.tinkerpop.machine.traverser.TraverserFactory;
 
 import java.util.Iterator;
 
@@ -31,14 +31,17 @@ import java.util.Iterator;
 public final class FlatMapInitial<C, S> extends AbstractFunction<C> implements InitialFunction<C, S> {
 
     private final Initializing<C, ?, S> function;
+    private final TraverserFactory<C> traverserFactory;
 
-    public FlatMapInitial(final Coefficient<C> coefficient, final String label, final Initializing<C, ?, S> function) {
+
+    public FlatMapInitial(final Coefficient<C> coefficient, final String label, final Initializing<C, ?, S> function, final TraverserFactory<C> traverserFactory) {
         super(coefficient, label);
         this.function = function;
+        this.traverserFactory = traverserFactory;
     }
 
     @Override
     public Iterator<S> get() {
-        return this.function.apply(EmptyTraverser.instance());
+        return this.function.apply(traverserFactory.create(this, null));
     }
 }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/EmptyProcessor.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/EmptyProcessor.java
similarity index 91%
rename from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/EmptyProcessor.java
rename to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/EmptyProcessor.java
index d3da9cb..a56bb98 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/EmptyProcessor.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/EmptyProcessor.java
@@ -16,11 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.processor;
+package org.apache.tinkerpop.machine.processor.util;
 
 import org.apache.tinkerpop.machine.bytecode.compiler.Compilation;
+import org.apache.tinkerpop.machine.processor.Processor;
+import org.apache.tinkerpop.machine.processor.ProcessorFactory;
 import org.apache.tinkerpop.machine.traverser.Traverser;
-import org.apache.tinkerpop.machine.util.FastNoSuchElementException;
 
 import java.util.Collections;
 import java.util.Iterator;
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/FilterProcessor.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/FilterProcessor.java
similarity index 96%
rename from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/FilterProcessor.java
rename to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/FilterProcessor.java
index a83e0d9..61294f7 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/FilterProcessor.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/FilterProcessor.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.processor;
+package org.apache.tinkerpop.machine.processor.util;
 
 import org.apache.tinkerpop.machine.traverser.Traverser;
 
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/LoopsProcessor.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/LoopsProcessor.java
similarity index 96%
rename from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/LoopsProcessor.java
rename to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/LoopsProcessor.java
index 25a44e1..9d97f82 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/LoopsProcessor.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/LoopsProcessor.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.processor;
+package org.apache.tinkerpop.machine.processor.util;
 
 import org.apache.tinkerpop.machine.traverser.Traverser;
 
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/SimpleProcessor.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/SimpleProcessor.java
similarity index 93%
rename from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/SimpleProcessor.java
rename to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/SimpleProcessor.java
index e2a0955..95b3edf 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/SimpleProcessor.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/processor/util/SimpleProcessor.java
@@ -16,9 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.processor;
+package org.apache.tinkerpop.machine.processor.util;
 
 import org.apache.tinkerpop.machine.bytecode.compiler.Compilation;
+import org.apache.tinkerpop.machine.processor.Processor;
+import org.apache.tinkerpop.machine.processor.ProcessorFactory;
 import org.apache.tinkerpop.machine.traverser.Traverser;
 import org.apache.tinkerpop.machine.util.FastNoSuchElementException;
 
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TSymbol.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TSymbol.java
deleted file mode 100644
index 67891ba..0000000
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TSymbol.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.machine.structure;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public interface TSymbol {
-
-}
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/IdSymbol.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/IdSymbol.java
deleted file mode 100644
index 43f6b8f..0000000
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/IdSymbol.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.machine.structure.graph;
-
-import org.apache.tinkerpop.machine.structure.TSymbol;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-final class IdSymbol implements TSymbol {
-
-    private static final IdSymbol INSTANCE = new IdSymbol();
-
-    private IdSymbol() {
-        // static instance
-    }
-
-    @Override
-    public String toString() {
-        return "#id";
-    }
-
-    @Override
-    public int hashCode() {
-        return this.toString().hashCode();
-    }
-
-    @Override
-    public boolean equals(final Object other) {
-        return other instanceof IdSymbol;
-    }
-
-    public static IdSymbol instance() {
-        return INSTANCE;
-    }
-}
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/LabelSymbol.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/LabelSymbol.java
deleted file mode 100644
index cbeb33b..0000000
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/LabelSymbol.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.machine.structure.graph;
-
-import org.apache.tinkerpop.machine.structure.TSymbol;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-final class LabelSymbol implements TSymbol {
-
-    private static final LabelSymbol INSTANCE = new LabelSymbol();
-
-    private LabelSymbol() {
-        // static instance
-    }
-
-    @Override
-    public String toString() {
-        return "#label";
-    }
-
-    @Override
-    public int hashCode() {
-        return this.toString().hashCode();
-    }
-
-    @Override
-    public boolean equals(final Object other) {
-        return other instanceof LabelSymbol;
-    }
-
-    public static LabelSymbol instance() {
-        return INSTANCE;
-    }
-}
\ No newline at end of file
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/TGraph.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/TGraph.java
index f0fa9b4..6b8f122 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/TGraph.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/TGraph.java
@@ -18,11 +18,11 @@
  */
 package org.apache.tinkerpop.machine.structure.graph;
 
+import org.apache.tinkerpop.machine.structure.Structure;
 import org.apache.tinkerpop.machine.structure.TSequence;
-import org.apache.tinkerpop.machine.structure.TTuple;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public interface TGraph extends TSequence<TVertex> {
+public interface TGraph extends TSequence<TVertex>, Structure {
 }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/TVertices.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/TVertices.java
deleted file mode 100644
index 90890b2..0000000
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/TVertices.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.machine.structure.graph;
-
-import org.apache.tinkerpop.machine.structure.TSequence;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public interface TVertices extends TSequence<TVertex> {
-}
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/EmptyStructure.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/EmptyStructure.java
similarity index 87%
rename from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/EmptyStructure.java
rename to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/EmptyStructure.java
index a00abb7..a367dc1 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/EmptyStructure.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/EmptyStructure.java
@@ -16,9 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.structure;
+package org.apache.tinkerpop.machine.structure.util;
 
-import java.util.Map;
+import org.apache.tinkerpop.machine.structure.Structure;
+import org.apache.tinkerpop.machine.structure.StructureFactory;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/JTuple.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/JTuple.java
index 5966aa2..46f5cf9 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/JTuple.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/JTuple.java
@@ -79,4 +79,9 @@ public class JTuple<K, V> implements TTuple<K, V> {
         return IteratorUtils.map(this.map.entrySet().iterator(), e -> new J2Tuple<>(e.getKey(), e.getValue()));
     }
 
+    @Override
+    public String toString() {
+        return this.map.toString();
+    }
+
 }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/G.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/TSymbol.java
similarity index 63%
rename from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/G.java
rename to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/TSymbol.java
index 5b0f6d0..a5ffd61 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/G.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/TSymbol.java
@@ -16,19 +16,27 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.structure.graph;
-
-import org.apache.tinkerpop.machine.structure.TSymbol;
+package org.apache.tinkerpop.machine.structure.util;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class G {
+public final class TSymbol {
 
-    private G() {
+    private TSymbol() {
         // static instance
     }
 
-    public static TSymbol id = IdSymbol.instance();
-    public static TSymbol label = LabelSymbol.instance();
+    public static final String id = "#id";
+    public static final String label = "#label";
+    public static final String key = "#key";
+    public static final String value = "#value";
+
+    public static boolean isSymbol(final String string) {
+        return string.startsWith("#");
+    }
+
+    public static String asSymbol(final String string) {
+        return string.startsWith("#") ? string : "#" + string;
+    }
 }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/BasicPath.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/BasicPath.java
index 5b7f078..5b46c9e 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/BasicPath.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/BasicPath.java
@@ -79,6 +79,7 @@ public final class BasicPath implements Path {
 
     @Override
     public Object get(final Pop pop, final String label) {
+       System.out.println(this.labels + ":::" + this.objects);
         if (Pop.last == pop) {
             for (int i = this.labels.size() - 1; i >= 0; i--) {
                 if (label.equals(this.labels.get(i)))
diff --git a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCDatabase.java b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCDatabase.java
index b04e894..3e4e93f 100644
--- a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCDatabase.java
+++ b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCDatabase.java
@@ -33,7 +33,7 @@ import java.util.Iterator;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-final class JDBCDatabase implements TDatabase {
+public final class JDBCDatabase implements TDatabase {
 
     private final Connection connection;
 
@@ -45,6 +45,10 @@ final class JDBCDatabase implements TDatabase {
         }
     }
 
+    public Connection getConnection() {
+        return this.connection;
+    }
+
     @Override
     public boolean has(final String key) {
         try {
diff --git a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCStructure.java b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCStructure.java
index 8c6a2ab..f951075 100644
--- a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCStructure.java
+++ b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCStructure.java
@@ -18,11 +18,15 @@
  */
 package org.apache.tinkerpop.machine.structure.jdbc;
 
+import org.apache.tinkerpop.machine.bytecode.compiler.BytecodeCompiler;
 import org.apache.tinkerpop.machine.strategy.Strategy;
 import org.apache.tinkerpop.machine.structure.Structure;
 import org.apache.tinkerpop.machine.structure.StructureFactory;
+import org.apache.tinkerpop.machine.structure.jdbc.bytecode.compiler.JDBCCompiler;
+import org.apache.tinkerpop.machine.structure.jdbc.strategy.JDBCQueryStrategy;
 import org.apache.tinkerpop.machine.structure.jdbc.strategy.JDBCStrategy;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -41,11 +45,16 @@ public class JDBCStructure implements StructureFactory {
 
     @Override
     public Set<Strategy<?>> getStrategies() {
-        return Set.of(new JDBCStrategy());
+        return Set.of(new JDBCStrategy(), new JDBCQueryStrategy());
     }
 
     @Override
     public Structure mint() {
         return new JDBCDatabase((String) this.configuration.get(JDBC_CONNECTION));
     }
+
+    @Override
+    public List<BytecodeCompiler> getCompilers() {
+        return List.of(JDBCCompiler.instance());
+    }
 }
diff --git a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/bytecode/compiler/JDBCCompiler.java b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/bytecode/compiler/JDBCCompiler.java
new file mode 100644
index 0000000..eb75b44
--- /dev/null
+++ b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/bytecode/compiler/JDBCCompiler.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.machine.structure.jdbc.bytecode.compiler;
+
+import org.apache.tinkerpop.machine.bytecode.Instruction;
+import org.apache.tinkerpop.machine.bytecode.compiler.BytecodeCompiler;
+import org.apache.tinkerpop.machine.bytecode.compiler.FunctionType;
+import org.apache.tinkerpop.machine.coefficient.Coefficient;
+import org.apache.tinkerpop.machine.function.CFunction;
+import org.apache.tinkerpop.machine.structure.jdbc.function.flatmap.SqlFlatMap;
+
+import java.sql.Connection;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class JDBCCompiler implements BytecodeCompiler {
+
+    private static final JDBCCompiler INSTANCE = new JDBCCompiler();
+
+    private JDBCCompiler() {
+        // static instance
+    }
+
+    public static JDBCCompiler instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public <C> CFunction<C> compile(final Instruction<C> instruction) {
+        final String op = instruction.op();
+        final Coefficient<C> coefficient = instruction.coefficient();
+        final String label = instruction.label();
+        if (op.equals(Symbols.JDBC_SQL))
+            return new SqlFlatMap<>(coefficient, label, (Connection) instruction.args()[0], (String) instruction.args()[1], (String) instruction.args()[2], (String) instruction.args()[3]);
+        else
+            return null;
+    }
+
+    @Override
+    public FunctionType getFunctionType(final String op) {
+        return op.equals(Symbols.JDBC_SQL) ? FunctionType.FLATMAP : null;
+    }
+
+    public static class Symbols {
+
+        private Symbols() {
+            // static instance
+        }
+
+        public static final String JDBC_SQL = "jdbc:sql";
+    }
+}
diff --git a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/function/flatmap/SqlFlatMap.java b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/function/flatmap/SqlFlatMap.java
new file mode 100644
index 0000000..af5f2b0
--- /dev/null
+++ b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/function/flatmap/SqlFlatMap.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.machine.structure.jdbc.function.flatmap;
+
+import org.apache.tinkerpop.machine.coefficient.Coefficient;
+import org.apache.tinkerpop.machine.function.AbstractFunction;
+import org.apache.tinkerpop.machine.function.initial.Initializing;
+import org.apache.tinkerpop.machine.structure.TTuple;
+import org.apache.tinkerpop.machine.structure.util.JTuple;
+import org.apache.tinkerpop.machine.traverser.Traverser;
+import org.apache.tinkerpop.machine.traverser.path.BasicPath;
+import org.apache.tinkerpop.machine.traverser.path.Path;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class SqlFlatMap<C, S> extends AbstractFunction<C> implements Initializing<C, S, Path> {
+
+    private final Connection connection;
+    private final String sqlQuery;
+    private final String as1;
+    private final String as2;
+
+    public SqlFlatMap(final Coefficient<C> coefficient, final String label, final Connection connection, final String as1, final String as2, final String sqlQuery) {
+        super(coefficient, label);
+        this.connection = connection;
+        this.sqlQuery = sqlQuery;
+        this.as1 = as1;
+        this.as2 = as2;
+    }
+
+    @Override
+    public Iterator<Path> apply(final Traverser<C, S> traverser) {
+        try {
+            final ResultSet resultSet = this.connection.createStatement().executeQuery(this.sqlQuery);
+            return new Iterator<>() {
+                boolean done = false;
+
+                @Override
+                public boolean hasNext() {
+                    return !this.done;
+                }
+
+                @Override
+                public Path next() {
+                    try {
+                        resultSet.next();
+                        int size = resultSet.getMetaData().getColumnCount();
+                        final Path row = new BasicPath();
+                        final TTuple<String, Object> tuple1 = new JTuple<>();
+                        final TTuple<String, Object> tuple2 = new JTuple<>();
+                        Set<String> labels = new HashSet<>();
+                        boolean stay = true;
+                        for (int i = 1; i <= size; i++) {
+                            final String temp = resultSet.getMetaData().getColumnLabel(i);
+                            stay = stay && labels.add(temp);
+                            if (stay) {
+                                tuple1.set(resultSet.getMetaData().getColumnName(i), resultSet.getObject(i));
+                            } else {
+                                tuple2.set(resultSet.getMetaData().getColumnName(i), resultSet.getObject(i));
+                            }
+                        }
+                        row.add(as1, tuple1);
+                        row.add(as2, tuple2);
+                        this.done = resultSet.isLast();
+                        return row;
+
+                    } catch (final SQLException e) {
+                        throw new RuntimeException(e.getMessage(), e);
+                    }
+                }
+            };
+        } catch (final SQLException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public SqlFlatMap<C, S> clone() {
+        return this; // TODO;
+    }
+}
diff --git a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/strategy/JDBCQueryStrategy.java b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/strategy/JDBCQueryStrategy.java
new file mode 100644
index 0000000..3adb915
--- /dev/null
+++ b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/strategy/JDBCQueryStrategy.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.machine.structure.jdbc.strategy;
+
+import org.apache.tinkerpop.machine.bytecode.Bytecode;
+import org.apache.tinkerpop.machine.bytecode.BytecodeUtil;
+import org.apache.tinkerpop.machine.bytecode.Instruction;
+import org.apache.tinkerpop.machine.bytecode.compiler.CoreCompiler.Symbols;
+import org.apache.tinkerpop.machine.strategy.AbstractStrategy;
+import org.apache.tinkerpop.machine.strategy.Strategy;
+import org.apache.tinkerpop.machine.structure.jdbc.JDBCDatabase;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class JDBCQueryStrategy extends AbstractStrategy<Strategy.ProviderStrategy> implements Strategy.ProviderStrategy {
+
+    @Override
+    public <C> void apply(final Bytecode<C> bytecode) {
+        if (bytecode.getParent().isEmpty() && BytecodeUtil.startsWith(bytecode, Symbols.DB, Symbols.VALUES, Symbols.DB, Symbols.VALUES, Symbols.HAS_KEY_VALUE, Symbols.PATH)) {
+            System.out.println(bytecode);
+            final JDBCDatabase db = (JDBCDatabase) bytecode.getInstructions().get(0).args()[0];
+            bytecode.getInstructions().remove(0); // DB
+            final String table1 = (String) bytecode.getInstructions().get(0).args()[0];
+            final String as1 = bytecode.getInstructions().get(0).label();
+            bytecode.getInstructions().remove(0); // VALUES
+            bytecode.getInstructions().remove(0); // DB
+            final String table2 = (String) bytecode.getInstructions().get(0).args()[0];
+            final String as2 = bytecode.getInstructions().get(0).label();
+            bytecode.getInstructions().remove(0); // VALUES
+            final String join = as1 + "." + bytecode.getInstructions().get(0).args()[0] + "=" + as2 + "." + ((Bytecode<C>) ((Bytecode<C>) bytecode.getInstructions().get(0).args()[1]).getInstructions().get(0).args()[1]).getInstructions().get(0).args()[0];
+            final String query = "SELECT " + as1 + ".*, " + as2 + ".* FROM " + table1 + " AS " + as1 + ", " + table2 + " AS " + as2 + " WHERE " + join;
+            final Instruction<C> inst = bytecode.getInstructions().remove(0); // HAS_KEY_VALUE
+            bytecode.getInstructions().remove(0); // PATH
+            bytecode.addInstruction(0, inst.coefficient(), "jdbc:sql", db.getConnection(), as1, as2, query);
+            System.out.println(bytecode);
+        }
+    }
+}
diff --git a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/strategy/JDBCStrategy.java b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/strategy/JDBCStrategy.java
index fc3b154..60a3c28 100644
--- a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/strategy/JDBCStrategy.java
+++ b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/strategy/JDBCStrategy.java
@@ -26,7 +26,9 @@ import org.apache.tinkerpop.machine.strategy.AbstractStrategy;
 import org.apache.tinkerpop.machine.strategy.Strategy;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -49,4 +51,9 @@ public final class JDBCStrategy extends AbstractStrategy<Strategy.ProviderStrate
                             BytecodeUtil.getStructureFactory(BytecodeUtil.getRootBytecode(bytecode)).get().mint()));
         }
     }
+
+    @Override
+    public Set<Class<? extends ProviderStrategy>> applyPost() {
+        return Set.of(JDBCQueryStrategy.class);
+    }
 }
diff --git a/java/machine/structure/jdbc/src/test/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCTest.java b/java/machine/structure/jdbc/src/test/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCTest.java
index 6429f07..1fa6c6c 100644
--- a/java/machine/structure/jdbc/src/test/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCTest.java
+++ b/java/machine/structure/jdbc/src/test/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCTest.java
@@ -41,8 +41,13 @@ public class JDBCTest {
         connection.createStatement().execute("CREATE TABLE IF NOT EXISTS people (\n" +
                 "    name VARCHAR(255) NOT NULL,\n" +
                 "    age TINYINT NOT NULL)");
+        connection.createStatement().execute("CREATE TABLE IF NOT EXISTS addresses (\n" +
+                "    name VARCHAR(255) NOT NULL,\n" +
+                "    city VARCHAR(255) NOT NULL)");
         //connection.createStatement().execute("INSERT INTO people(`name`,`age`) VALUES ('marko',29)");
         //connection.createStatement().execute("INSERT INTO people(`name`,`age`) VALUES ('josh',32)");
+        //connection.createStatement().execute("INSERT INTO addresses(`name`,`city`) VALUES ('josh','san jose')");
+        //connection.createStatement().execute("INSERT INTO addresses(`name`,`city`) VALUES ('marko','santa fe')");
 
 
        /* final TDatabase db = new JDBCDatabase("jdbc:h2:/tmp/test");
@@ -67,6 +72,7 @@ public class JDBCTest {
         System.out.println(jdbc.db().values("people").toList());
         System.out.println(jdbc.db().values("people").value("name").toList());
         System.out.println(jdbc.db().values("people").entries().toList());
-        System.out.println(jdbc.db().values("people").as("x").db().values("people").has("name", __.path("x").by("name")).as("y").path("x", "y").toList());
+        System.out.println(jdbc.db().values("people").as("x").db().values("addresses").as("y").has("name", __.path("x").by("name")).path("x", "y").toList());
+        System.out.println(jdbc.db().values("people").as("x").db().values("addresses").as("y").has("name", __.path("x").by("name")).path("x", "y").explain().toList());
     }
 }