Merge changes from topic 'baku'

* changes:
  Baku - incrementally adding docs
  Baku - Usability improvements
  Baku - Derived SG suffixes
  Baku - Fixing cloud sync permissions.
  Baku Toolkit - Fixing blessings stuff
  Baku Toolkit - upgrading to BlessingsManager
diff --git a/lib/src/main/java/io/v/v23/syncbase/nosql/DatabaseCore.java b/lib/src/main/java/io/v/v23/syncbase/nosql/DatabaseCore.java
index 5be7120..dc810f6 100644
--- a/lib/src/main/java/io/v/v23/syncbase/nosql/DatabaseCore.java
+++ b/lib/src/main/java/io/v/v23/syncbase/nosql/DatabaseCore.java
@@ -10,6 +10,7 @@
 import io.v.v23.services.watch.ResumeMarker;
 import io.v.v23.vdl.VdlAny;
 
+import java.lang.reflect.Type;
 import java.util.List;
 
 import javax.annotation.CheckReturnValue;
@@ -77,6 +78,23 @@
     ListenableFuture<QueryResults> exec(VContext context, String query);
 
     /**
+     * Executes a SyncQL parameterized query. Same as {@link #exec(VContext, String)}, with the
+     * query supporting positional parameters. {@code paramValues} and {@code paramTypes} must each
+     * have one element corresponding to each '?' placeholder in the query.
+     *
+     * @param  context      Vanadium context
+     * @param  query        a SyncQL query
+     * @param  paramValues  SyncQL query parameters, one per '?' placeholder in the query
+     * @param  paramTypes   SyncQL query parameter types, one per parameter in paramValues
+     * @return              a {@link ListenableFuture} whose result is a {@link QueryResults}
+     *                      object that allows the caller to iterate over arrays of values for each
+     *                      row that matches the query
+     */
+    @CheckReturnValue
+    ListenableFuture<QueryResults> exec(VContext context, String query,
+                                        List<Object> paramValues, List<Type> paramTypes);
+
+    /**
      * Returns a new {@link ListenableFuture} whose result is the {@link ResumeMarker} that points
      * to the current state of the database.
      * <p>
diff --git a/lib/src/main/java/io/v/v23/syncbase/nosql/DatabaseImpl.java b/lib/src/main/java/io/v/v23/syncbase/nosql/DatabaseImpl.java
index bf2f04a..e1a7127 100644
--- a/lib/src/main/java/io/v/v23/syncbase/nosql/DatabaseImpl.java
+++ b/lib/src/main/java/io/v/v23/syncbase/nosql/DatabaseImpl.java
@@ -5,6 +5,7 @@
 package io.v.v23.syncbase.nosql;
 
 import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -35,8 +36,10 @@
 import io.v.v23.vdl.VdlAny;
 import io.v.v23.vdl.VdlOptional;
 import io.v.v23.verror.VException;
+import io.v.v23.vom.VomUtil;
 
 import java.io.Serializable;
+import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -98,17 +101,27 @@
     }
     @Override
     public ListenableFuture<QueryResults> exec(VContext ctx, String query) {
-        final ClientRecvStream<List<VdlAny>, Void> stream =
-                client.exec(ctx, getSchemaVersion(), query);
-        return VFutures.withUserLandChecks(ctx, Futures.transform(stream.recv(),
-                new AsyncFunction<List<VdlAny>, QueryResults>() {
-                    @Override
-                    public ListenableFuture<QueryResults> apply(List<VdlAny> columnNames)
-                            throws Exception {
-                        return Futures.immediateFuture(
-                                (QueryResults) new QueryResultsImpl(columnNames, stream));
-                    }
-                }));
+        return this.execInternal(ctx, query, null);
+    }
+    @Override
+    public ListenableFuture<QueryResults> exec(VContext ctx, String query,
+                                               List<Object> paramValues, List<Type> paramTypes) {
+        Preconditions.checkNotNull(paramValues);
+        Preconditions.checkNotNull(paramTypes);
+        if (paramValues.size() != paramTypes.size()) {
+            throw new IllegalArgumentException("Length of paramValues and paramTypes is not equal");
+        }
+        List<VdlAny> params = new ArrayList<VdlAny>();
+        try {
+            Iterator<Object> v = paramValues.iterator();
+            Iterator<Type> t = paramTypes.iterator();
+            while (v.hasNext() && t.hasNext()) {
+                params.add(new VdlAny(VomUtil.valueOf(v.next(), t.next())));
+            }
+        } catch (VException e) {
+            return VFutures.withUserLandChecks(ctx, Futures.<QueryResults>immediateFailedFuture(e));
+        }
+        return this.execInternal(ctx, query, params);
     }
 
     // Implements AccessController interface.
@@ -292,6 +305,20 @@
                 watchChange.getContinued());
     }
 
+    private ListenableFuture<QueryResults> execInternal(VContext ctx, String query, List<VdlAny> params) {
+        final ClientRecvStream<List<VdlAny>, Void> stream =
+                client.exec(ctx, getSchemaVersion(), query, params);
+        return VFutures.withUserLandChecks(ctx, Futures.transform(stream.recv(),
+                new AsyncFunction<List<VdlAny>, QueryResults>() {
+                    @Override
+                    public ListenableFuture<QueryResults> apply(List<VdlAny> columnNames)
+                            throws Exception {
+                        return Futures.immediateFuture(
+                                (QueryResults) new QueryResultsImpl(columnNames, stream));
+                    }
+                }));
+    }
+
     private static List<String> splitInTwo(String str, String separator) {
         Iterator<String> iter = Splitter.on(separator).limit(2).split(str).iterator();
         return ImmutableList.of(
diff --git a/lib/src/test/java/io/v/v23/syncbase/SyncbaseTest.java b/lib/src/test/java/io/v/v23/syncbase/SyncbaseTest.java
index 4df616a..10ae922 100644
--- a/lib/src/test/java/io/v/v23/syncbase/SyncbaseTest.java
+++ b/lib/src/test/java/io/v/v23/syncbase/SyncbaseTest.java
@@ -49,6 +49,8 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Serializable;
+import java.lang.reflect.Type;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 
@@ -226,6 +228,17 @@
                     ImmutableList.of(new VdlAny(String.class, "foo"), new VdlAny(Foo.class, foo))
             );
         }
+        {
+            DatabaseCore.QueryResults results = sync(db.exec(ctx,
+                "select k, v from " + TABLE_NAME + " where k = ? or v.I = ?",
+                Arrays.<Object>asList("baz", 4),
+                Arrays.<Type>asList(String.class, int.class)));
+            assertThat(results.columnNames()).containsExactly("k", "v");
+            assertThat(sync(InputChannels.asList(results))).containsExactly(
+                    ImmutableList.of(new VdlAny(String.class, "baz"), new VdlAny(Baz.class, baz)),
+                    ImmutableList.of(new VdlAny(String.class, "foo"), new VdlAny(Foo.class, foo))
+            );
+        }
     }
 
     public void testDatabaseWatch() throws Exception {