aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2019-05-07 12:03:42 +0800
committerTing-Wei Lan <tingwei.lan@cobinhood.com>2019-05-14 11:04:15 +0800
commit9aa6fb4c7a219c4431f52eb241f36dc5cfe040d5 (patch)
tree44c427e41e371168c915daaf5b2753a690705f7d
parent1fb67a439f5725a7926592f55f59e82486641155 (diff)
downloaddexon-9aa6fb4c7a219c4431f52eb241f36dc5cfe040d5.tar
dexon-9aa6fb4c7a219c4431f52eb241f36dc5cfe040d5.tar.gz
dexon-9aa6fb4c7a219c4431f52eb241f36dc5cfe040d5.tar.bz2
dexon-9aa6fb4c7a219c4431f52eb241f36dc5cfe040d5.tar.lz
dexon-9aa6fb4c7a219c4431f52eb241f36dc5cfe040d5.tar.xz
dexon-9aa6fb4c7a219c4431f52eb241f36dc5cfe040d5.tar.zst
dexon-9aa6fb4c7a219c4431f52eb241f36dc5cfe040d5.zip
code backup 34
-rw-r--r--core/vm/sqlvm/checker/expr.go124
1 files changed, 123 insertions, 1 deletions
diff --git a/core/vm/sqlvm/checker/expr.go b/core/vm/sqlvm/checker/expr.go
index f9421a32e..01c673709 100644
--- a/core/vm/sqlvm/checker/expr.go
+++ b/core/vm/sqlvm/checker/expr.go
@@ -92,7 +92,7 @@ func checkExpr(n ast.ExprNode,
return checkModOperator(n, s, o, c, el, tr, ta)
case *ast.IsOperatorNode:
- return n
+ return checkIsOperator(n, s, o, c, el, tr, ta)
case *ast.LikeOperatorNode:
return n
@@ -1157,6 +1157,9 @@ func checkParenOperator(n *ast.ParenOperatorNode,
r := n.GetTarget()
r = checkExpr(r, s, o, c, el, tr, ta)
+ if r == nil {
+ return nil
+ }
r.SetPosition(n.GetPosition())
r.SetLength(n.GetLength())
r.SetToken(n.GetToken())
@@ -2297,3 +2300,122 @@ func checkModOperator(n *ast.ModOperatorNode,
return r
})
}
+
+func checkIsOperator(n *ast.IsOperatorNode,
+ s schema.Schema, o CheckOptions, c *schemaCache, el *errors.ErrorList,
+ tr schema.TableRef, ta typeAction) ast.ExprNode {
+
+ fn := "CheckIsOperator"
+ op := "binary operator IS"
+
+ object := n.GetObject()
+ object = checkExpr(object, s, o, c, el, tr, nil)
+ if object == nil {
+ return nil
+ }
+ subject := n.GetSubject()
+ subject = checkExpr(subject, s, o, c, el, tr, nil)
+ if subject == nil {
+ return nil
+ }
+ n.SetObject(object)
+ n.SetSubject(subject)
+ r := ast.ExprNode(n)
+
+ reportUnsupportedConstant := func(n ast.Valuer) {
+ el.Append(errors.Error{
+ Position: n.GetPosition(),
+ Length: n.GetLength(),
+ Category: errors.ErrorCategorySemantic,
+ Code: errors.ErrorCodeTypeError,
+ Severity: errors.ErrorSeverityError,
+ Prefix: fn,
+ Message: fmt.Sprintf(
+ "the right-hand side of %s cannot be %s",
+ op, describeValueNodeType(n)),
+ }, nil)
+ }
+ reportNotConstant := func(n ast.ExprNode) {
+ el.Append(errors.Error{
+ Position: n.GetPosition(),
+ Length: n.GetLength(),
+ Category: errors.ErrorCategorySemantic,
+ Code: errors.ErrorCodeNonConstantExpression,
+ Severity: errors.ErrorSeverityError,
+ Prefix: fn,
+ Message: fmt.Sprintf(
+ "the right-hand side of %s is not a constant", op),
+ }, nil)
+ }
+ var is ast.BoolValue
+ if sv, ok := subject.(ast.Valuer); ok {
+ switch sn := sv.(type) {
+ case *ast.BoolValueNode:
+ // IS TRUE / FALSE / UNKNOWN only works for bool.
+ if !validateBoolType(object.GetType(), el, object, fn, op) {
+ return nil
+ }
+ is = sn.V
+ op = "unary operator IS " + is.String()
+ case *ast.NullValueNode:
+ // IS NULL works for all types.
+ op = "unary operator IS NULL"
+ case *ast.AddressValueNode:
+ reportUnsupportedConstant(sv)
+ return nil
+ case *ast.IntegerValueNode:
+ reportUnsupportedConstant(sv)
+ return nil
+ case *ast.DecimalValueNode:
+ reportUnsupportedConstant(sv)
+ return nil
+ case *ast.BytesValueNode:
+ reportUnsupportedConstant(sv)
+ return nil
+ default:
+ panic(unknownValueNodeType(sv))
+ }
+ } else {
+ reportNotConstant(subject)
+ return nil
+ }
+ dt := n.GetType()
+
+ if object, ok := object.(ast.Valuer); ok {
+ var vo ast.BoolValue
+ if _, isBool := object.(*ast.BoolValueNode); isBool && !is.Valid() {
+ // Redirect IS NULL to IS UNKNOWN for bool.
+ is = ast.BoolValueUnknown
+ }
+ if is.Valid() {
+ // IS TRUE / FALSE / UNKNOWN
+ v, ok := extractBoolValue(object, el, fn, op)
+ if !ok {
+ return nil
+ }
+ vo = ast.NewBoolValueFromBool(v == is)
+ } else {
+ // IS NULL
+ _, isNull := object.(*ast.NullValueNode)
+ vo = ast.NewBoolValueFromBool(isNull)
+ }
+ node := &ast.BoolValueNode{}
+ node.SetPosition(n.GetPosition())
+ node.SetLength(n.GetLength())
+ node.SetToken(n.GetToken())
+ node.V = vo
+ r = node
+ }
+
+ switch a := ta.(type) {
+ case typeActionInferDefault:
+ case typeActionInferWithSize:
+ case typeActionInferWithMajor:
+ case typeActionAssign:
+ if !dt.Equal(a.dt) {
+ elAppendTypeErrorAssignDataType(el, n, fn, a.dt, dt)
+ return nil
+ }
+ }
+ return r
+}