Repository: vitessio/vitess
Pull request #6470 (2020-07-24 16:18:45)

block lock function usage other than dual table
Signed-off-by: Harshit Gangal <harshit@planetscale.com>


Patch:
diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go
index 9ccb1eb9c9..489c659115 100644
--- a/go/vt/vtgate/planbuilder/select.go
+++ b/go/vt/vtgate/planbuilder/select.go
@@ -89,6 +89,12 @@ func buildSelectPlan(stmt sqlparser.Statement, vschema ContextVSchema) (engine.P
 // pushed into a route, then a primitive is created on top of any
 // of the above trees to make it discard unwanted rows.
 func (pb *primitiveBuilder) processSelect(sel *sqlparser.Select, outer *symtab) error {
+	// Check and error if there is any locking function present in select expression.
+	for _, expr := range sel.SelectExprs {
+		if aExpr, ok := expr.(*sqlparser.AliasedExpr); ok && sqlparser.IsLockingFunc(aExpr.Expr) {
+			return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "%v allowed only with dual", sqlparser.String(aExpr))
+		}
+	}
 	if sel.SQLCalcFoundRows && sel.Limit != nil {
 		return vterrors.Errorf(vtrpc.Code_UNIMPLEMENTED, "sql_calc_found_rows not yet fully supported")
 	}


Test patch:
diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go
index 215b7d3bf9..b307f4c4d3 100644
--- a/go/vt/vtgate/planbuilder/plan_test.go
+++ b/go/vt/vtgate/planbuilder/plan_test.go
@@ -175,6 +175,7 @@ func TestPlan(t *testing.T) {
 	testFile(t, "set_sysvar_cases.txt", testOutputTempDir, vschemaWrapper)
 	testFile(t, "union_cases.txt", testOutputTempDir, vschemaWrapper)
 	testFile(t, "transaction_cases.txt", testOutputTempDir, vschemaWrapper)
+	testFile(t, "lock_cases.txt", testOutputTempDir, vschemaWrapper)
 }
 
 func TestOne(t *testing.T) {
@@ -323,7 +324,7 @@ func (vw *vschemaWrapper) AnyKeyspace() (*vindexes.Keyspace, error) {
 }
 
 func (vw *vschemaWrapper) FirstSortedKeyspace() (*vindexes.Keyspace, error) {
-	panic("implement me")
+	return vw.v.Keyspaces["main"].Keyspace, nil
 }
 
 func (vw *vschemaWrapper) TargetString() string {
diff --git a/go/vt/vtgate/planbuilder/testdata/lock_cases.txt b/go/vt/vtgate/planbuilder/testdata/lock_cases.txt
new file mode 100644
index 0000000000..1599bb99a3
--- /dev/null
+++ b/go/vt/vtgate/planbuilder/testdata/lock_cases.txt
@@ -0,0 +1,19 @@
+# get_lock from dual
+"select get_lock('xyz', 10) from dual"
+{
+  "QueryType": "SELECT",
+  "Original": "select get_lock('xyz', 10) from dual",
+  "Instructions": {
+    "OperatorType": "Reserve"
+  }
+}
+
+# is_free_lock from dual
+"select is_free_lock('xyz') from dual"
+{
+  "QueryType": "SELECT",
+  "Original": "select is_free_lock('xyz') from dual",
+  "Instructions": {
+    "OperatorType": "Reserve"
+  }
+}
diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
index bae077d6c2..3dc5f49dfe 100644
--- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt
@@ -419,3 +419,15 @@
 # ambiguous LIMIT
 "select id from user limit 1 union all select id from music limit 1"
 "Incorrect usage of UNION and LIMIT - add parens to disambiguate your query (errno 1221) (sqlstate 21000)"
+
+# select get_lock with non-dual table
+"select get_lock('xyz', 10) from user"
+"get_lock('xyz', 10) allowed only with dual"
+
+# select is_free_lock with non-dual table
+"select is_free_lock('xyz') from user"
+"is_free_lock('xyz') allowed only with dual"
+
+# insert using select get_lock from table
+"insert into user(pattern) SELECT GET_LOCK('xyz1', 10)"
+"unsupported: insert into select"