You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2019/04/29 15:15:06 UTC

[tinkerpop] branch tp4 updated: Generalized path() to work with no, one, or many labels. Have INNER JOIN working with jdbc/. Path now implements TTuple and is thus, subject to has(), value(), entries(), etc.

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

okram pushed a commit to branch tp4
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/tp4 by this push:
     new 706ad64  Generalized path() to work with no, one, or many labels. Have INNER JOIN working with jdbc/. Path now implements TTuple and is thus, subject to has(), value(), entries(), etc.
706ad64 is described below

commit 706ad64b78ba1144276294805f325d7cd44ea024
Author: Marko A. Rodriguez <ok...@gmail.com>
AuthorDate: Mon Apr 29 09:14:50 2019 -0600

    Generalized path() to work with no, one, or many labels. Have INNER JOIN working with jdbc/. Path now implements TTuple and is thus, subject to has(), value(), entries(), etc.
---
 .../tinkerpop/language/gremlin/Traversal.java      | 12 ++++-
 .../language/gremlin/TraversalSource.java          |  2 +-
 .../language/gremlin/core/CoreTraversal.java       | 30 ++++++++++-
 .../apache/tinkerpop/language/gremlin/core/__.java | 13 +++++
 .../tinkerpop/machine/bytecode/Bytecode.java       |  1 +
 .../machine/bytecode/compiler/CoreCompiler.java    |  5 ++
 .../machine/function/filter/HasKeyFilter.java      |  8 ++-
 .../DbInitial.java => flatmap/EntriesFlatMap.java} | 33 ++++++------
 .../machine/function/initial/DbInitial.java        | 18 +++++--
 .../machine/function/reduce/GroupCountReduce.java  |  4 +-
 .../tinkerpop/machine/structure/TSequence.java     |  4 ++
 .../apache/tinkerpop/machine/structure/TTuple.java |  8 ++-
 .../structure/graph/{LabelSymbol.java => G.java}   |  9 +++-
 .../machine/structure/graph/IdSymbol.java          | 27 +++++++++-
 .../machine/structure/graph/LabelSymbol.java       | 29 ++++++++++-
 .../tinkerpop/machine/structure/graph/TGraph.java  |  2 +-
 .../structure/{table => rdbms}/TDatabase.java      |  5 +-
 .../machine/structure/{table => rdbms}/TRow.java   |  2 +-
 .../machine/structure/{table => rdbms}/TTable.java |  2 +-
 .../tinkerpop/machine/structure/util/J2Tuple.java  | 18 +++++--
 .../{graph/TGraph.java => util/JSequence.java}     | 26 ++++++++--
 .../tinkerpop/machine/structure/util/JTuple.java   | 26 +++++++++-
 .../machine/traverser/path/BasicPath.java          | 35 +++++++++++++
 .../machine/traverser/path/EmptyPath.java          | 30 +++++++++++
 .../tinkerpop/machine/traverser/path/Path.java     |  4 +-
 .../tinkerpop/machine/processor/pipes/Pipes.java   |  6 +--
 .../blueprints/data/BlueprintsVertex.java          | 14 +++++-
 .../machine/structure/jdbc/JDBCDatabase.java       | 58 +++++++++++++++++++---
 .../tinkerpop/machine/structure/jdbc/JDBCRow.java  | 45 +++++++++++++++--
 .../machine/structure/jdbc/JDBCStructure.java      |  4 +-
 .../machine/structure/jdbc/JDBCTable.java          | 25 +++++++++-
 .../structure/jdbc/strategy/JDBCStrategy.java      | 13 +++--
 .../tinkerpop/machine/structure/jdbc/JDBCTest.java | 17 +++++--
 33 files changed, 460 insertions(+), 75 deletions(-)

diff --git a/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/Traversal.java b/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/Traversal.java
index c281220..5015a9e 100644
--- a/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/Traversal.java
+++ b/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/Traversal.java
@@ -20,6 +20,8 @@ package org.apache.tinkerpop.language.gremlin;
 
 import org.apache.tinkerpop.machine.bytecode.compiler.Order;
 import org.apache.tinkerpop.machine.structure.TTuple;
+import org.apache.tinkerpop.machine.structure.rdbms.TDatabase;
+import org.apache.tinkerpop.machine.structure.util.T2Tuple;
 import org.apache.tinkerpop.machine.traverser.Traverser;
 import org.apache.tinkerpop.machine.traverser.path.Path;
 
@@ -53,10 +55,14 @@ public interface Traversal<C, S, E> extends Iterator<E> {
 
     public Traversal<C, S, Long> count();
 
+    public Traversal<C, S, TDatabase> db();
+
     public Traversal<C, S, E> emit();
 
     public Traversal<C, S, E> emit(final Traversal<C, ?, ?> emitTraversal); // TODO: why not <C,E,?>
 
+    public <K, V> Traversal<C, S, T2Tuple<K, V>> entries();
+
     public Traversal<C, S, String> explain();
 
     public Traversal<C, S, E> filter(final Traversal<C, E, ?> filterTraversal);
@@ -95,7 +101,11 @@ public interface Traversal<C, S, E> extends Iterator<E> {
 
     public Traversal<C, S, E> order();
 
-    public Traversal<C, S, Path> path(final String... labels);
+    public Traversal<C, S, Path> path();
+
+    public <R> Traversal<C, S, R> path(final String label);
+
+    public Traversal<C, S, Path> path(final String label, final String... labels);
 
     public Traversal<C, S, E> repeat(final Traversal<C, E, E> repeatTraversal);
 
diff --git a/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/TraversalSource.java b/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/TraversalSource.java
index 82f3ddc..bcbf648 100644
--- a/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/TraversalSource.java
+++ b/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/TraversalSource.java
@@ -32,7 +32,7 @@ import org.apache.tinkerpop.machine.strategy.finalization.CoefficientStrategy;
 import org.apache.tinkerpop.machine.strategy.verification.CoefficientVerificationStrategy;
 import org.apache.tinkerpop.machine.structure.StructureFactory;
 import org.apache.tinkerpop.machine.structure.graph.TVertex;
-import org.apache.tinkerpop.machine.structure.table.TDatabase;
+import org.apache.tinkerpop.machine.structure.rdbms.TDatabase;
 
 import java.util.Map;
 
diff --git a/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/core/CoreTraversal.java b/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/core/CoreTraversal.java
index 111613c..86f2329 100644
--- a/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/core/CoreTraversal.java
+++ b/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/core/CoreTraversal.java
@@ -30,6 +30,8 @@ import org.apache.tinkerpop.machine.bytecode.compiler.Pred;
 import org.apache.tinkerpop.machine.coefficient.Coefficient;
 import org.apache.tinkerpop.machine.coefficient.LongCoefficient;
 import org.apache.tinkerpop.machine.structure.TTuple;
+import org.apache.tinkerpop.machine.structure.rdbms.TDatabase;
+import org.apache.tinkerpop.machine.structure.util.T2Tuple;
 import org.apache.tinkerpop.machine.traverser.path.Path;
 
 /**
@@ -109,6 +111,11 @@ public class CoreTraversal<C, S, E> extends AbstractTraversal<C, S, E> {
     }
 
     @Override
+    public Traversal<C, S, TDatabase> db() {
+        return this.addInstruction(Symbols.DB);
+    }
+
+    @Override
     public Traversal<C, S, E> emit() {
         return TraversalUtil.insertRepeatInstruction(this, 'e', true);
     }
@@ -119,6 +126,11 @@ public class CoreTraversal<C, S, E> extends AbstractTraversal<C, S, E> {
     }
 
     @Override
+    public <K, V> Traversal<C, S, T2Tuple<K, V>> entries() {
+        return this.addInstruction(Symbols.ENTRIES);
+    }
+
+    @Override
     public Traversal<C, S, String> explain() {
         return this.addInstruction(Symbols.EXPLAIN);
     }
@@ -214,8 +226,22 @@ public class CoreTraversal<C, S, E> extends AbstractTraversal<C, S, E> {
     }
 
     @Override
-    public Traversal<C, S, Path> path(final String... labels) {
-        return this.addInstruction(Symbols.PATH, TraversalUtil.addObjects(labels, "|"));
+    public Traversal<C, S, Path> path() {
+        return this.addInstruction(Symbols.PATH, "|");
+    }
+
+    @Override
+    public <R> Traversal<C, S, R> path(final String label) {
+        this.addInstruction(Symbols.PATH, label, "|");
+        return (Traversal) this.addInstruction(Symbols.VALUE, label);
+    }
+
+    @Override
+    public Traversal<C, S, Path> path(final String label, final String... labels) {
+        this.addInstruction(Symbols.PATH, label);
+        this.bytecode.addArgs((Object[]) labels);
+        this.bytecode.addArgs("|");
+        return (Traversal) this;
     }
 
     @Override
diff --git a/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/core/__.java b/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/core/__.java
index 72f13a1..77b3a40 100644
--- a/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/core/__.java
+++ b/java/language/gremlin/src/main/java/org/apache/tinkerpop/language/gremlin/core/__.java
@@ -20,6 +20,7 @@ package org.apache.tinkerpop.language.gremlin.core;
 
 import org.apache.tinkerpop.language.gremlin.P;
 import org.apache.tinkerpop.language.gremlin.Traversal;
+import org.apache.tinkerpop.machine.traverser.path.Path;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -82,6 +83,18 @@ public class __ {
         return __.<C, S>start().map(traversal);
     }
 
+    public static <C, S> Traversal<C, S, Path> path() {
+        return __.<C, S>start().path();
+    }
+
+    public static <C, S, R> Traversal<C, S, R> path(final String label) {
+        return __.<C, S>start().path(label);
+    }
+
+    public static <C, S> Traversal<C, S, Path> path(final String label, final String... labels) {
+        return __.<C, S>start().path(label, labels);
+    }
+
     public static <C, S extends Number> Traversal<C, S, S> sum() {
         return __.<C, S>start().sum();
     }
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 42216f5..eeeeacc 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
@@ -110,6 +110,7 @@ public final class Bytecode<C> implements Cloneable, Serializable {
             }
             for (final Instruction<C> instruction : this.instructions) {
                 clone.addInstruction(instruction.coefficient(), instruction.op(), instruction.args());
+                clone.lastInstruction().setLabel(instruction.label());
             }
             return clone;
         } catch (final CloneNotSupportedException e) {
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/CoreCompiler.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/CoreCompiler.java
index d7f2904..b77011b 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/CoreCompiler.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/CoreCompiler.java
@@ -30,6 +30,7 @@ import org.apache.tinkerpop.machine.function.filter.HasKeyFilter;
 import org.apache.tinkerpop.machine.function.filter.HasKeyValueFilter;
 import org.apache.tinkerpop.machine.function.filter.IdentityFilter;
 import org.apache.tinkerpop.machine.function.filter.IsFilter;
+import org.apache.tinkerpop.machine.function.flatmap.EntriesFlatMap;
 import org.apache.tinkerpop.machine.function.flatmap.FlatMapFlatMap;
 import org.apache.tinkerpop.machine.function.flatmap.UnfoldFlatMap;
 import org.apache.tinkerpop.machine.function.flatmap.ValuesFlatMap;
@@ -69,6 +70,7 @@ public final class CoreCompiler implements BytecodeCompiler {
         put(Symbols.BRANCH, FunctionType.BRANCH);
         put(Symbols.CONSTANT, FunctionType.MAP);
         put(Symbols.COUNT, FunctionType.REDUCE);
+        put(Symbols.ENTRIES, FunctionType.FLATMAP);
         put(Symbols.FILTER, FunctionType.FILTER);
         put(Symbols.FLATMAP, FunctionType.FLATMAP);
         put(Symbols.GROUP_COUNT, FunctionType.REDUCE);
@@ -106,6 +108,8 @@ public final class CoreCompiler implements BytecodeCompiler {
                 return ConstantMap.compile(instruction);
             case Symbols.COUNT:
                 return CountReduce.compile(instruction);
+            case Symbols.ENTRIES:
+                return EntriesFlatMap.compile(instruction);
             case Symbols.FILTER:
                 return FilterFilter.compile(instruction);
             case Symbols.FLATMAP:
@@ -192,6 +196,7 @@ public final class CoreCompiler implements BytecodeCompiler {
         public static final String BRANCH = "branch";
         public static final String CONSTANT = "constant";
         public static final String COUNT = "count";
+        public static final String ENTRIES = "entries";
         public static final String EXPLAIN = "explain";
         public static final String FILTER = "filter";
         public static final String FLATMAP = "flatmap";
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java
index 835bf4d..d6ef5db 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java
@@ -24,11 +24,13 @@ import org.apache.tinkerpop.machine.bytecode.compiler.Pred;
 import org.apache.tinkerpop.machine.coefficient.Coefficient;
 import org.apache.tinkerpop.machine.function.AbstractFunction;
 import org.apache.tinkerpop.machine.function.FilterFunction;
-import org.apache.tinkerpop.machine.structure.util.T2Tuple;
 import org.apache.tinkerpop.machine.structure.TTuple;
+import org.apache.tinkerpop.machine.structure.util.T2Tuple;
 import org.apache.tinkerpop.machine.traverser.Traverser;
 import org.apache.tinkerpop.machine.util.StringFactory;
 
+import java.util.Iterator;
+
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
@@ -50,7 +52,9 @@ public final class HasKeyFilter<C, K, V> extends AbstractFunction<C> implements
             return object.has(this.key.mapArg(traverser));
         else {
             final K testKey = this.key.mapArg(traverser);
-            for (final T2Tuple<K, V> entry : traverser.object().entries()) {
+            final Iterator<T2Tuple<K, V>> iterator = traverser.object().entries();
+            while (iterator.hasNext()) {
+                final T2Tuple<K, V> entry = iterator.next();
                 if (this.predicate.test(entry.key(), testKey))
                     return true;
             }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/DbInitial.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/flatmap/EntriesFlatMap.java
similarity index 56%
copy from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/DbInitial.java
copy to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/flatmap/EntriesFlatMap.java
index 9b983b6..4143cc5 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/DbInitial.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/flatmap/EntriesFlatMap.java
@@ -16,47 +16,50 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.function.initial;
+package org.apache.tinkerpop.machine.function.flatmap;
 
 import org.apache.tinkerpop.machine.bytecode.Instruction;
 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.structure.table.TDatabase;
+import org.apache.tinkerpop.machine.function.FlatMapFunction;
+import org.apache.tinkerpop.machine.structure.TTuple;
+import org.apache.tinkerpop.machine.structure.util.T2Tuple;
+import org.apache.tinkerpop.machine.traverser.Traverser;
 import org.apache.tinkerpop.machine.util.StringFactory;
 
 import java.util.Iterator;
-import java.util.List;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class DbInitial<C> extends AbstractFunction<C> implements InitialFunction<C, TDatabase> {
+public final class EntriesFlatMap<C, K, V> extends AbstractFunction<C> implements FlatMapFunction<C, TTuple<K, V>, T2Tuple<K, V>> {
 
-    private TDatabase database;
 
-    private DbInitial(final Coefficient<C> coefficient, final String label, final TDatabase database) {
+    private EntriesFlatMap(final Coefficient<C> coefficient, final String label) {
         super(coefficient, label);
-        this.database = database;
     }
 
+    @Override
+    public Iterator<T2Tuple<K, V>> apply(final Traverser<C, TTuple<K, V>> traverser) {
+        return traverser.object().entries();
+    }
 
     @Override
-    public Iterator<TDatabase> get() {
-        return List.of(this.database).iterator();
+    public EntriesFlatMap<C, K, V> clone() {
+        return (EntriesFlatMap<C, K, V>) super.clone();
     }
 
     @Override
     public int hashCode() {
-        return super.hashCode() ^ this.database.hashCode();
+        return super.hashCode();
     }
 
     @Override
     public String toString() {
-        return StringFactory.makeFunctionString(this, this.database);
+        return StringFactory.makeFunctionString(this);
     }
 
-    public static <C> DbInitial<C> compile(final Instruction<C> instruction) {
-        return new DbInitial<>(instruction.coefficient(), instruction.label(), (TDatabase) instruction.args()[0]);
+    public static <C, K, V> EntriesFlatMap<C, K, V> compile(final Instruction<C> instruction) {
+        return new EntriesFlatMap<>(instruction.coefficient(), instruction.label());
     }
-}
+}
\ No newline at end of file
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/DbInitial.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/DbInitial.java
index 9b983b6..246f072 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/DbInitial.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/DbInitial.java
@@ -22,7 +22,9 @@ import org.apache.tinkerpop.machine.bytecode.Instruction;
 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.structure.table.TDatabase;
+import org.apache.tinkerpop.machine.function.MapFunction;
+import org.apache.tinkerpop.machine.structure.rdbms.TDatabase;
+import org.apache.tinkerpop.machine.traverser.Traverser;
 import org.apache.tinkerpop.machine.util.StringFactory;
 
 import java.util.Iterator;
@@ -31,7 +33,7 @@ import java.util.List;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class DbInitial<C> extends AbstractFunction<C> implements InitialFunction<C, TDatabase> {
+public final class DbInitial<C, S> extends AbstractFunction<C> implements InitialFunction<C, TDatabase>, MapFunction<C, S, TDatabase> {
 
     private TDatabase database;
 
@@ -56,7 +58,17 @@ public final class DbInitial<C> extends AbstractFunction<C> implements InitialFu
         return StringFactory.makeFunctionString(this, this.database);
     }
 
-    public static <C> DbInitial<C> compile(final Instruction<C> instruction) {
+    public static <C, S> DbInitial<C, S> compile(final Instruction<C> instruction) {
         return new DbInitial<>(instruction.coefficient(), instruction.label(), (TDatabase) instruction.args()[0]);
     }
+
+    @Override
+    public TDatabase apply(final Traverser<C, S> traverser) {
+        return this.database;
+    }
+
+    @Override
+    public DbInitial<C, S> clone() {
+        return this;
+    }
 }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/reduce/GroupCountReduce.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/reduce/GroupCountReduce.java
index 89eadb2..6549ad2 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/reduce/GroupCountReduce.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/reduce/GroupCountReduce.java
@@ -50,8 +50,8 @@ public final class GroupCountReduce<C, S, E> extends AbstractFunction<C> impleme
     @Override
     public TTuple<E, Long> merge(final TTuple<E, Long> valueA, final TTuple<E, Long> valueB) {
         final JTuple<E, Long> tuple = new JTuple<>();
-        valueA.entries().forEach(entry -> tuple.set(entry.key(), entry.value()));
-        valueB.entries().forEach(entry -> tuple.set(entry.key(), entry.value()));
+        valueA.entries().forEachRemaining(entry -> tuple.set(entry.key(), entry.value()));
+        valueB.entries().forEachRemaining(entry -> tuple.set(entry.key(), entry.value()));
         return new JTuple<>();
     }
 
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TSequence.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TSequence.java
index 7e6ceba..7c57095 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TSequence.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TSequence.java
@@ -23,4 +23,8 @@ package org.apache.tinkerpop.machine.structure;
  */
 public interface TSequence<V> extends Iterable<V> {
 
+    public void add(final V value);
+
+    public void remove(final V value);
+
 }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TTuple.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TTuple.java
index 8228291..c324caf 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TTuple.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/TTuple.java
@@ -20,6 +20,8 @@ package org.apache.tinkerpop.machine.structure;
 
 import org.apache.tinkerpop.machine.structure.util.T2Tuple;
 
+import java.util.Iterator;
+
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
@@ -35,6 +37,10 @@ public interface TTuple<K, V> {
 
     public void set(final K key, final V value);
 
-    public TSequence<T2Tuple<K, V>> entries();
+    public void add(final K key, final V value);
+
+    public void remove(final K key);
+
+    public Iterator<T2Tuple<K, V>> entries();
 
 }
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/G.java
similarity index 84%
copy from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/LabelSymbol.java
copy to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/G.java
index 09ae9f8..5b0f6d0 100644
--- 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/G.java
@@ -23,5 +23,12 @@ import org.apache.tinkerpop.machine.structure.TSymbol;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public class LabelSymbol implements TSymbol {
+public final class G {
+
+    private G() {
+        // static instance
+    }
+
+    public static TSymbol id = IdSymbol.instance();
+    public static TSymbol label = LabelSymbol.instance();
 }
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
index bda1787..43f6b8f 100644
--- 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
@@ -23,5 +23,30 @@ import org.apache.tinkerpop.machine.structure.TSymbol;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public class IdSymbol implements TSymbol {
+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
index 09ae9f8..cbeb33b 100644
--- 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
@@ -23,5 +23,30 @@ import org.apache.tinkerpop.machine.structure.TSymbol;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public class LabelSymbol implements TSymbol {
-}
+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 d515a33..f0fa9b4 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
@@ -24,5 +24,5 @@ import org.apache.tinkerpop.machine.structure.TTuple;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public interface TGraph extends TTuple<String, TSequence<TVertex>> {
+public interface TGraph extends TSequence<TVertex> {
 }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/table/TDatabase.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/rdbms/TDatabase.java
similarity index 83%
rename from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/table/TDatabase.java
rename to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/rdbms/TDatabase.java
index 445ed33..56d5157 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/table/TDatabase.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/rdbms/TDatabase.java
@@ -16,12 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.structure.table;
+package org.apache.tinkerpop.machine.structure.rdbms;
 
+import org.apache.tinkerpop.machine.structure.Structure;
 import org.apache.tinkerpop.machine.structure.TTuple;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public interface TDatabase extends TTuple<String,TTable> {
+public interface TDatabase extends TTuple<String, TTable>, Structure {
 }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/table/TRow.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/rdbms/TRow.java
similarity index 94%
rename from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/table/TRow.java
rename to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/rdbms/TRow.java
index d4161bb..d80e399 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/table/TRow.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/rdbms/TRow.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.structure.table;
+package org.apache.tinkerpop.machine.structure.rdbms;
 
 import org.apache.tinkerpop.machine.structure.TTuple;
 
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/table/TTable.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/rdbms/TTable.java
similarity index 94%
rename from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/table/TTable.java
rename to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/rdbms/TTable.java
index f3d7679..ba447f4 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/table/TTable.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/rdbms/TTable.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.structure.table;
+package org.apache.tinkerpop.machine.structure.rdbms;
 
 import org.apache.tinkerpop.machine.structure.TSequence;
 
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/J2Tuple.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/J2Tuple.java
index 4827f71..e94e138 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/J2Tuple.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/J2Tuple.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.machine.structure.util;
 
-import org.apache.tinkerpop.machine.structure.TSequence;
+import org.apache.tinkerpop.machine.util.IteratorUtils;
 
-import java.util.List;
+import java.util.Iterator;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -56,8 +56,18 @@ public final class J2Tuple<K, V> implements T2Tuple<K, V> {
     }
 
     @Override
-    public TSequence<T2Tuple<K, V>> entries() {
-        return () -> List.of((T2Tuple<K, V>) this).iterator();
+    public void add(final K key, final V value) {
+        throw new IllegalStateException("Can't add key/value for a 2-tuple");
+    }
+
+    @Override
+    public void remove(final K key) {
+        throw new IllegalStateException("Can't remove key/value for a 2-tuple");
+    }
+
+    @Override
+    public Iterator<T2Tuple<K, V>> entries() {
+        return IteratorUtils.of(this);
     }
 
     @Override
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/util/JSequence.java
similarity index 64%
copy from java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/graph/TGraph.java
copy to java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/structure/util/JSequence.java
index d515a33..6b54a54 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/util/JSequence.java
@@ -16,13 +16,33 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.machine.structure.graph;
+package org.apache.tinkerpop.machine.structure.util;
 
 import org.apache.tinkerpop.machine.structure.TSequence;
-import org.apache.tinkerpop.machine.structure.TTuple;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public interface TGraph extends TTuple<String, TSequence<TVertex>> {
+public final class JSequence<V> implements TSequence<V> {
+
+    private final List<V> list = new ArrayList<>();
+
+    @Override
+    public void add(final V value) {
+        this.list.add(value);
+    }
+
+    @Override
+    public void remove(final V value) {
+        this.list.remove(value);
+    }
+
+    @Override
+    public Iterator<V> iterator() {
+        return this.list.iterator();
+    }
 }
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 edff5bd..7f59f9a 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
@@ -23,6 +23,7 @@ import org.apache.tinkerpop.machine.structure.TTuple;
 import org.apache.tinkerpop.machine.util.IteratorUtils;
 
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 
 /**
@@ -48,8 +49,29 @@ public class JTuple<K, V> implements TTuple<K, V> {
     }
 
     @Override
-    public TSequence<T2Tuple<K, V>> entries() {
-        return () -> IteratorUtils.map(this.map.entrySet().iterator(), e -> new J2Tuple<>(e.getKey(), e.getValue()));
+    public void add(final K key, final V value) {
+        if (this.map.containsKey(key)) {
+            final Object v = this.map.get(key);
+            if (v instanceof TSequence) {
+                ((TSequence) v).add(v);
+            } else {
+                final JSequence sequence = new JSequence();
+                sequence.add(v);
+                this.map.put(key, (V) sequence);
+            }
+        } else {
+            this.map.put(key, value);
+        }
+    }
+
+    @Override
+    public void remove(final K key) {
+        this.map.remove(key);
+    }
+
+    @Override
+    public Iterator<T2Tuple<K, V>> entries() {
+        return IteratorUtils.map(this.map.entrySet().iterator(), e -> new J2Tuple<>(e.getKey(), e.getValue()));
     }
 
 }
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 e1844c0..19c3736 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
@@ -18,7 +18,11 @@
  */
 package org.apache.tinkerpop.machine.traverser.path;
 
+import org.apache.tinkerpop.machine.structure.util.T2Tuple;
+import org.apache.tinkerpop.machine.util.IteratorUtils;
+
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -33,12 +37,43 @@ public final class BasicPath implements Path {
     }
 
     @Override
+    public boolean has(final String key) {
+        return this.labels.contains(key);
+    }
+
+    @Override
+    public Object value(final String key) {
+        return this.get(Pop.last, key);
+    }
+
+    @Override
+    public void set(final String key, final Object value) {
+        final int index = this.labels.indexOf(key);
+        if (-1 != index)
+            this.objects.set(index, value);
+    }
+
+    @Override
     public void add(final String label, final Object object) {
         this.labels.add(label);
         this.objects.add(object);
     }
 
     @Override
+    public void remove(final String key) {
+        final int index = this.labels.indexOf(key);
+        if (-1 != index) {
+            this.labels.remove(index);
+            this.objects.remove(index);
+        }
+    }
+
+    @Override
+    public Iterator<T2Tuple<String, Object>> entries() {
+        return null;
+    }
+
+    @Override
     public Object object(final int index) {
         return this.objects.get(index);
     }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/EmptyPath.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/EmptyPath.java
index b8c5c7c..b3b0a6d 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/EmptyPath.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/EmptyPath.java
@@ -18,6 +18,11 @@
  */
 package org.apache.tinkerpop.machine.traverser.path;
 
+import org.apache.tinkerpop.machine.structure.util.T2Tuple;
+
+import java.util.Collections;
+import java.util.Iterator;
+
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
@@ -30,11 +35,36 @@ public final class EmptyPath implements Path {
     }
 
     @Override
+    public boolean has(final String key) {
+        return false;
+    }
+
+    @Override
+    public Object value(final String key) {
+        throw new IllegalStateException("No objects in EmptyPath");
+    }
+
+    @Override
+    public void set(final String key, final Object value) {
+
+    }
+
+    @Override
     public void add(final String label, final Object object) {
 
     }
 
     @Override
+    public void remove(final String key) {
+
+    }
+
+    @Override
+    public Iterator<T2Tuple<String, Object>> entries() {
+        return Collections.emptyIterator();
+    }
+
+    @Override
     public Object object(int index) {
         throw new IllegalStateException("No objects in EmptyPath");
     }
diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/Path.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/Path.java
index eb853b9..cd911b5 100644
--- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/Path.java
+++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/traverser/path/Path.java
@@ -18,12 +18,14 @@
  */
 package org.apache.tinkerpop.machine.traverser.path;
 
+import org.apache.tinkerpop.machine.structure.TTuple;
+
 import java.io.Serializable;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public interface Path extends Serializable, Cloneable {
+public interface Path extends Serializable, Cloneable, TTuple<String,Object> {
 
     public enum Pop {
         first, last, all;
diff --git a/java/machine/processor/pipes/src/main/java/org/apache/tinkerpop/machine/processor/pipes/Pipes.java b/java/machine/processor/pipes/src/main/java/org/apache/tinkerpop/machine/processor/pipes/Pipes.java
index cc5a4cf..f93f644 100644
--- a/java/machine/processor/pipes/src/main/java/org/apache/tinkerpop/machine/processor/pipes/Pipes.java
+++ b/java/machine/processor/pipes/src/main/java/org/apache/tinkerpop/machine/processor/pipes/Pipes.java
@@ -59,7 +59,9 @@ public final class Pipes<C, S, E> implements Processor<C, S, E> {
                 previousStep = this.startStep;
             }
 
-            if (function instanceof RepeatBranch)
+            if (this.steps.isEmpty() && function instanceof InitialFunction)
+                nextStep = new InitialStep<>((InitialFunction<C, S>) function, compilation.getTraverserFactory()); // TODO: this is a hack for DB
+            else if (function instanceof RepeatBranch)
                 nextStep = new RepeatStep<>(previousStep, (RepeatBranch<C, S>) function);
             else if (function instanceof BranchFunction)
                 nextStep = new BranchStep<>(previousStep, (BranchFunction<C, S, E>) function);
@@ -69,8 +71,6 @@ public final class Pipes<C, S, E> implements Processor<C, S, E> {
                 nextStep = new FlatMapStep<>(previousStep, (FlatMapFunction<C, S, E>) function);
             else if (function instanceof MapFunction)
                 nextStep = new MapStep<>(previousStep, (MapFunction<C, S, E>) function);
-            else if (function instanceof InitialFunction)
-                nextStep = new InitialStep<>((InitialFunction<C, S>) function, compilation.getTraverserFactory());
             else if (function instanceof BarrierFunction)
                 nextStep = new BarrierStep<>(previousStep, (BarrierFunction<C, S, E, Object>) function, compilation.getTraverserFactory());
             else if (function instanceof ReduceFunction)
diff --git a/java/machine/structure/blueprints/src/main/java/org/apache/tinkerpop/machine/structure/blueprints/data/BlueprintsVertex.java b/java/machine/structure/blueprints/src/main/java/org/apache/tinkerpop/machine/structure/blueprints/data/BlueprintsVertex.java
index a88b146..fa08d24 100644
--- a/java/machine/structure/blueprints/src/main/java/org/apache/tinkerpop/machine/structure/blueprints/data/BlueprintsVertex.java
+++ b/java/machine/structure/blueprints/src/main/java/org/apache/tinkerpop/machine/structure/blueprints/data/BlueprintsVertex.java
@@ -59,6 +59,16 @@ public class BlueprintsVertex<V> implements TVertex<V>, Serializable {
     }
 
     @Override
+    public void add(String key, V value) {
+
+    }
+
+    @Override
+    public void remove(String key) {
+
+    }
+
+    @Override
     public V value(String key) {
         return (V) "marko";
     }
@@ -74,8 +84,8 @@ public class BlueprintsVertex<V> implements TVertex<V>, Serializable {
     }
 
     @Override
-    public TSequence<T2Tuple<String, V>> entries() {
-        return Collections::emptyIterator;
+    public Iterator<T2Tuple<String, V>> entries() {
+        return Collections.emptyIterator();
     }
 
     @Override
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 cad8d9c..ed57e74 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
@@ -18,21 +18,21 @@
  */
 package org.apache.tinkerpop.machine.structure.jdbc;
 
-import org.apache.tinkerpop.machine.structure.Structure;
-import org.apache.tinkerpop.machine.structure.TSequence;
-import org.apache.tinkerpop.machine.structure.table.TDatabase;
-import org.apache.tinkerpop.machine.structure.table.TTable;
+import org.apache.tinkerpop.machine.structure.rdbms.TDatabase;
+import org.apache.tinkerpop.machine.structure.rdbms.TTable;
+import org.apache.tinkerpop.machine.structure.util.J2Tuple;
 import org.apache.tinkerpop.machine.structure.util.T2Tuple;
 
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.Iterator;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-final class JDBCDatabase implements TDatabase, Structure {
+final class JDBCDatabase implements TDatabase {
 
     private final Connection connection;
 
@@ -69,8 +69,52 @@ final class JDBCDatabase implements TDatabase, Structure {
     }
 
     @Override
-    public TSequence<T2Tuple<String, TTable>> entries() {
-        return null;
+    public void add(final String key, final TTable value) {
+        // TODO
+    }
+
+    @Override
+    public void remove(final String key) {
+        try {
+            this.connection.createStatement().execute("DROP TABLE " + key);
+        } catch (final SQLException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public Iterator<T2Tuple<String, TTable>> entries() {
+        try {
+            final ResultSet result = this.connection.createStatement().executeQuery("SHOW TABLES");
+            return new Iterator<>() {
+                boolean done = false;
+
+                @Override
+                public boolean hasNext() {
+                    return !this.done;
+                }
+
+                @Override
+                public T2Tuple<String, TTable> next() {
+                    try {
+                        result.next();
+                        final String tableName = result.getString(1);
+                        final T2Tuple<String, TTable> tuple = new J2Tuple<>(tableName, new JDBCTable(connection, tableName));
+                        this.done = result.isLast();
+                        return tuple;
+                    } catch (final SQLException e) {
+                        throw new RuntimeException(e.getMessage(), e);
+                    }
+                }
+            };
+        } catch (final SQLException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "<database#" + this.connection + ">";
     }
 
 }
diff --git a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCRow.java b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCRow.java
index 57017ad..2591553 100644
--- a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCRow.java
+++ b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCRow.java
@@ -18,14 +18,15 @@
  */
 package org.apache.tinkerpop.machine.structure.jdbc;
 
-import org.apache.tinkerpop.machine.structure.TSequence;
-import org.apache.tinkerpop.machine.structure.table.TRow;
+import org.apache.tinkerpop.machine.structure.rdbms.TRow;
 import org.apache.tinkerpop.machine.structure.util.J2Tuple;
 import org.apache.tinkerpop.machine.structure.util.T2Tuple;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -73,10 +74,37 @@ final class JDBCRow<V> implements TRow<V> {
     }
 
     @Override
-    public TSequence<T2Tuple<String, V>> entries() {
+    public void add(final String key, final V value) {
         try {
             this.rows.absolute(this.rowId);
-            return () -> new Iterator<>() {
+            Object v = this.rows.getObject(key);
+            if (v instanceof List)
+                ((List) v).add(value);
+            else {
+                v = new ArrayList<>();
+                ((ArrayList) v).add(value);
+            }
+            this.rows.updateObject(key, v);
+        } catch (final SQLException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public void remove(final String key) {
+        try {
+            this.rows.absolute(this.rowId);
+            this.rows.updateObject(key, null);
+        } catch (final SQLException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public Iterator<T2Tuple<String, V>> entries() {
+        try {
+            this.rows.absolute(this.rowId);
+            return new Iterator<>() {
 
                 int column = 1;
 
@@ -104,4 +132,13 @@ final class JDBCRow<V> implements TRow<V> {
             throw new RuntimeException(e.getMessage(), e);
         }
     }
+
+    @Override
+    public String toString() {
+        try {
+            return "<row#" + this.rows.getMetaData().getTableName(1) + ":" + this.rowId + ">";
+        } catch (final SQLException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
 }
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 778a36b..8c6a2ab 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
@@ -31,6 +31,8 @@ import java.util.Set;
  */
 public class JDBCStructure implements StructureFactory {
 
+    public static final String JDBC_CONNECTION = "jdbc.connection";
+
     private final Map<String, Object> configuration;
 
     public JDBCStructure(final Map<String, Object> configuration) {
@@ -44,6 +46,6 @@ public class JDBCStructure implements StructureFactory {
 
     @Override
     public Structure mint() {
-        return new JDBCDatabase((String) this.configuration.get("jdbc.connection"));
+        return new JDBCDatabase((String) this.configuration.get(JDBC_CONNECTION));
     }
 }
diff --git a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCTable.java b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCTable.java
index de8b46a..a0b8cf5 100644
--- a/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCTable.java
+++ b/java/machine/structure/jdbc/src/main/java/org/apache/tinkerpop/machine/structure/jdbc/JDBCTable.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.machine.structure.jdbc;
 
-import org.apache.tinkerpop.machine.structure.table.TRow;
-import org.apache.tinkerpop.machine.structure.table.TTable;
+import org.apache.tinkerpop.machine.structure.rdbms.TRow;
+import org.apache.tinkerpop.machine.structure.rdbms.TTable;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
@@ -67,4 +67,25 @@ final class JDBCTable implements TTable {
             throw new RuntimeException(e.getMessage(), e);
         }
     }
+
+    @Override
+    public void add(final TRow<?> value) {
+        try {
+            this.connection.createStatement().executeUpdate("INSERT INTO " + this.name + " ()" + " VALUES (" + value + ")");
+        } catch (final SQLException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public void remove(final TRow<?> value) {
+        // TODO
+    }
+
+    @Override
+    public String toString() {
+        return "<table#" + this.name + ">";
+    }
+
+    // TODO: equals(), hashcode()
 }
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 84466cd..fc3b154 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
@@ -25,6 +25,9 @@ import org.apache.tinkerpop.machine.bytecode.compiler.CoreCompiler.Symbols;
 import org.apache.tinkerpop.machine.strategy.AbstractStrategy;
 import org.apache.tinkerpop.machine.strategy.Strategy;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
@@ -32,16 +35,16 @@ public final class JDBCStrategy extends AbstractStrategy<Strategy.ProviderStrate
 
     @Override
     public <C> void apply(final Bytecode<C> bytecode) {
-        Instruction<C> dbInstruction = null;
+        final List<Instruction<C>> dbInstructions = new ArrayList<>();
         for (final Instruction<C> instruction : bytecode.getInstructions()) {
             if (instruction.op().equals(Symbols.DB)) {
-                dbInstruction = instruction;
+                dbInstructions.add(instruction);
             }
         }
-        if (null != dbInstruction) {
-            BytecodeUtil.replaceInstruction(bytecode, dbInstruction,
+        for (final Instruction<C> instruction : dbInstructions) {
+            BytecodeUtil.replaceInstruction(bytecode, instruction,
                     new Instruction<>(
-                            dbInstruction.coefficient(),
+                            instruction.coefficient(),
                             Symbols.DB,
                             BytecodeUtil.getStructureFactory(BytecodeUtil.getRootBytecode(bytecode)).get().mint()));
         }
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 be9a7d2..242bba7 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
@@ -19,11 +19,11 @@
 package org.apache.tinkerpop.machine.structure.jdbc;
 
 import org.apache.tinkerpop.language.gremlin.Gremlin;
-import org.apache.tinkerpop.language.gremlin.P;
 import org.apache.tinkerpop.language.gremlin.TraversalSource;
+import org.apache.tinkerpop.language.gremlin.core.__;
 import org.apache.tinkerpop.machine.Machine;
 import org.apache.tinkerpop.machine.processor.pipes.PipesProcessor;
-import org.apache.tinkerpop.machine.species.BasicMachine;
+import org.apache.tinkerpop.machine.species.LocalMachine;
 import org.junit.jupiter.api.Test;
 
 import java.sql.Connection;
@@ -42,6 +42,7 @@ public class JDBCTest {
                 "    name VARCHAR(255) NOT NULL,\n" +
                 "    age TINYINT NOT NULL)");
         //connection.createStatement().execute("INSERT INTO people(`name`,`age`) VALUES ('marko',29)");
+        //connection.createStatement().execute("INSERT INTO people(`name`,`age`) VALUES ('josh',32)");
 
 
        /* final TDatabase db = new JDBCDatabase("jdbc:h2:/tmp/test");
@@ -55,11 +56,17 @@ public class JDBCTest {
 
         ////////
 
-        final Machine machine = BasicMachine.open();
+        final Machine machine = LocalMachine.open();
         final TraversalSource<Long> jdbc =
                 Gremlin.<Long>traversal(machine).
                         withProcessor(PipesProcessor.class).
-                        withStructure(JDBCStructure.class, Map.of("jdbc.connection", "jdbc:h2:/tmp/test"));
-        System.out.println(jdbc.db().values("people").hasKey(P.eq("age")).value("name").toList());
+                        withStructure(JDBCStructure.class, Map.of(JDBCStructure.JDBC_CONNECTION, "jdbc:h2:/tmp/test"));
+        System.out.println(jdbc.db().toList());
+        System.out.println(jdbc.db().entries().toList());
+        System.out.println(jdbc.db().value("people").toList());
+        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").value("name")).as("y").path("x", "y").toList());
     }
 }