From c8fd7f412af66040d7e1664f292d83a10807cdc4 Mon Sep 17 00:00:00 2001
From: Meng-Ying Yang <garfield@dexon.org>
Date: Mon, 6 May 2019 15:49:02 +0800
Subject: fixup! core: vm: sqlvm: add built-in function SUBSTRING()

---
 core/vm/sqlvm/runtime/functions.go | 48 ++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 18 deletions(-)

(limited to 'core/vm')

diff --git a/core/vm/sqlvm/runtime/functions.go b/core/vm/sqlvm/runtime/functions.go
index a05c791e7..45d6cec65 100644
--- a/core/vm/sqlvm/runtime/functions.go
+++ b/core/vm/sqlvm/runtime/functions.go
@@ -448,6 +448,12 @@ func fnSubString(ctx *common.Context, ops []*Operand, length uint64) (result *Op
 		return
 	}
 
+	if len(ops[0].Data) != len(ops[1].Data) ||
+		len(ops[0].Data) != len(ops[2].Data) {
+		err = se.ErrorCodeIndexOutOfRange
+		return
+	}
+
 	op := ops[0]
 
 	if !metaAllDynBytes(op) {
@@ -464,28 +470,34 @@ func fnSubString(ctx *common.Context, ops []*Operand, length uint64) (result *Op
 		result.Meta[i] = dynBytesType
 	}
 
-	starts, err := ops[1].toUint64()
-	if err == nil && len(starts) != 1 {
-		err = se.ErrorCodeIndexOutOfRange
-	}
-	if err != nil {
-		return
-	}
-
-	lens, err := ops[2].toUint64()
-	if err == nil && len(lens) != 1 {
-		err = se.ErrorCodeIndexOutOfRange
-	}
-	if err != nil {
-		return
-	}
-
-	start, end := starts[0], starts[0]+lens[0]
+	starts, ends := ops[1], ops[2]
 
+	var start, end uint64
 	for i := 0; i < len(op.Data); i++ {
 		result.Data[i] = make(Tuple, len(op.Data[i]))
+
+		if starts.IsImmediate {
+			start, err = ast.DecimalToUint64(starts.Data[0][0].Value)
+		} else {
+			start, err = ast.DecimalToUint64(starts.Data[i][0].Value)
+		}
+
+		if err != nil {
+			return
+		}
+
+		if ends.IsImmediate {
+			end, err = ast.DecimalToUint64(ends.Data[0][0].Value)
+		} else {
+			end, err = ast.DecimalToUint64(ends.Data[i][0].Value)
+		}
+
+		if err != nil {
+			return
+		}
+
 		for j := 0; j < len(op.Data[i]); j++ {
-			result.Data[i][j] = &Raw{Bytes: op.Data[i][j].Bytes[start:end]}
+			result.Data[i][j] = &Raw{Bytes: op.Data[i][j].Bytes[start : start+end]}
 		}
 	}
 	return
-- 
cgit v1.2.3