зеркало из https://github.com/github/vitess-gh.git
Add parsing support for JSON Utility Functions (#9850)
* feat: add parsing support for json utility functions Signed-off-by: Kushal Kumar <kushalkumargupta4@gmail.com> * refactor:use backticks in test_cases and remove unused field in JSONUtility struct Signed-off-by: Kushal Kumar <kushalkumargupta4@gmail.com> * tests: use backticks for strings Signed-off-by: Kushal Kumar <kushalkumargupta4@gmail.com> * refactor: use separate structs for each utility function Create separate structs and format function for each struct Update parser to use corresponding structs Remove previously used JSONUtilityExpr struct Signed-off-by: Kushal Kumar <kushalkumargupta4@gmail.com> * ci: fix number of expected conflicts Signed-off-by: Kushal Kumar <kushalkumargupta4@gmail.com> * test: add planner tests for the json utility functions Signed-off-by: Manan Gupta <manan@planetscale.com> Co-authored-by: Manan Gupta <manan@planetscale.com>
This commit is contained in:
Родитель
31bbb4fa32
Коммит
b93679f651
|
@ -2224,6 +2224,24 @@ type (
|
|||
alternative Expr // this is what will be used to Format this struct
|
||||
}
|
||||
|
||||
// JSONPrettyExpr represents the function and argument for JSON_PRETTY()
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/json-utility-functions.html#function_json-pretty
|
||||
JSONPrettyExpr struct {
|
||||
JSONVal Expr
|
||||
}
|
||||
|
||||
// JSONStorageFreeExpr represents the function and argument for JSON_STORAGE_FREE()
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/json-utility-functions.html#function_json-storage-free
|
||||
JSONStorageFreeExpr struct {
|
||||
JSONVal Expr
|
||||
}
|
||||
|
||||
// JSONStorageSizeExpr represents the function and argument for JSON_STORAGE_SIZE()
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/json-utility-functions.html#function_json-storage-size
|
||||
JSONStorageSizeExpr struct {
|
||||
JSONVal Expr
|
||||
}
|
||||
|
||||
// Offset is another AST type that is used during planning and never produced by the parser
|
||||
Offset int
|
||||
)
|
||||
|
@ -2264,6 +2282,9 @@ func (*MatchExpr) iExpr() {}
|
|||
func (*GroupConcatExpr) iExpr() {}
|
||||
func (*Default) iExpr() {}
|
||||
func (*ExtractedSubquery) iExpr() {}
|
||||
func (*JSONPrettyExpr) iExpr() {}
|
||||
func (*JSONStorageFreeExpr) iExpr() {}
|
||||
func (*JSONStorageSizeExpr) iExpr() {}
|
||||
func (*TrimFuncExpr) iExpr() {}
|
||||
func (Offset) iExpr() {}
|
||||
|
||||
|
@ -2280,6 +2301,9 @@ func (*SubstrExpr) iCallable() {}
|
|||
func (*ConvertUsingExpr) iCallable() {}
|
||||
func (*MatchExpr) iCallable() {}
|
||||
func (*GroupConcatExpr) iCallable() {}
|
||||
func (*JSONPrettyExpr) iCallable() {}
|
||||
func (*JSONStorageFreeExpr) iCallable() {}
|
||||
func (*JSONStorageSizeExpr) iCallable() {}
|
||||
|
||||
// Exprs represents a list of value expressions.
|
||||
// It's not a valid expression because it's not parenthesized.
|
||||
|
|
|
@ -173,6 +173,12 @@ func CloneSQLNode(in SQLNode) SQLNode {
|
|||
return CloneRefOfIsExpr(in)
|
||||
case IsolationLevel:
|
||||
return in
|
||||
case *JSONPrettyExpr:
|
||||
return CloneRefOfJSONPrettyExpr(in)
|
||||
case *JSONStorageFreeExpr:
|
||||
return CloneRefOfJSONStorageFreeExpr(in)
|
||||
case *JSONStorageSizeExpr:
|
||||
return CloneRefOfJSONStorageSizeExpr(in)
|
||||
case *JoinCondition:
|
||||
return CloneRefOfJoinCondition(in)
|
||||
case *JoinTableExpr:
|
||||
|
@ -1129,6 +1135,36 @@ func CloneRefOfIsExpr(n *IsExpr) *IsExpr {
|
|||
return &out
|
||||
}
|
||||
|
||||
// CloneRefOfJSONPrettyExpr creates a deep clone of the input.
|
||||
func CloneRefOfJSONPrettyExpr(n *JSONPrettyExpr) *JSONPrettyExpr {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
out := *n
|
||||
out.JSONVal = CloneExpr(n.JSONVal)
|
||||
return &out
|
||||
}
|
||||
|
||||
// CloneRefOfJSONStorageFreeExpr creates a deep clone of the input.
|
||||
func CloneRefOfJSONStorageFreeExpr(n *JSONStorageFreeExpr) *JSONStorageFreeExpr {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
out := *n
|
||||
out.JSONVal = CloneExpr(n.JSONVal)
|
||||
return &out
|
||||
}
|
||||
|
||||
// CloneRefOfJSONStorageSizeExpr creates a deep clone of the input.
|
||||
func CloneRefOfJSONStorageSizeExpr(n *JSONStorageSizeExpr) *JSONStorageSizeExpr {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
out := *n
|
||||
out.JSONVal = CloneExpr(n.JSONVal)
|
||||
return &out
|
||||
}
|
||||
|
||||
// CloneRefOfJoinCondition creates a deep clone of the input.
|
||||
func CloneRefOfJoinCondition(n *JoinCondition) *JoinCondition {
|
||||
if n == nil {
|
||||
|
@ -2106,6 +2142,12 @@ func CloneCallable(in Callable) Callable {
|
|||
return CloneRefOfFuncExpr(in)
|
||||
case *GroupConcatExpr:
|
||||
return CloneRefOfGroupConcatExpr(in)
|
||||
case *JSONPrettyExpr:
|
||||
return CloneRefOfJSONPrettyExpr(in)
|
||||
case *JSONStorageFreeExpr:
|
||||
return CloneRefOfJSONStorageFreeExpr(in)
|
||||
case *JSONStorageSizeExpr:
|
||||
return CloneRefOfJSONStorageSizeExpr(in)
|
||||
case *MatchExpr:
|
||||
return CloneRefOfMatchExpr(in)
|
||||
case *SubstrExpr:
|
||||
|
@ -2284,6 +2326,12 @@ func CloneExpr(in Expr) Expr {
|
|||
return CloneRefOfIntroducerExpr(in)
|
||||
case *IsExpr:
|
||||
return CloneRefOfIsExpr(in)
|
||||
case *JSONPrettyExpr:
|
||||
return CloneRefOfJSONPrettyExpr(in)
|
||||
case *JSONStorageFreeExpr:
|
||||
return CloneRefOfJSONStorageFreeExpr(in)
|
||||
case *JSONStorageSizeExpr:
|
||||
return CloneRefOfJSONStorageSizeExpr(in)
|
||||
case ListArg:
|
||||
return in
|
||||
case *Literal:
|
||||
|
|
|
@ -476,6 +476,24 @@ func EqualsSQLNode(inA, inB SQLNode) bool {
|
|||
return false
|
||||
}
|
||||
return a == b
|
||||
case *JSONPrettyExpr:
|
||||
b, ok := inB.(*JSONPrettyExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return EqualsRefOfJSONPrettyExpr(a, b)
|
||||
case *JSONStorageFreeExpr:
|
||||
b, ok := inB.(*JSONStorageFreeExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return EqualsRefOfJSONStorageFreeExpr(a, b)
|
||||
case *JSONStorageSizeExpr:
|
||||
b, ok := inB.(*JSONStorageSizeExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return EqualsRefOfJSONStorageSizeExpr(a, b)
|
||||
case *JoinCondition:
|
||||
b, ok := inB.(*JoinCondition)
|
||||
if !ok {
|
||||
|
@ -1935,6 +1953,39 @@ func EqualsRefOfIsExpr(a, b *IsExpr) bool {
|
|||
a.Right == b.Right
|
||||
}
|
||||
|
||||
// EqualsRefOfJSONPrettyExpr does deep equals between the two objects.
|
||||
func EqualsRefOfJSONPrettyExpr(a, b *JSONPrettyExpr) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
return EqualsExpr(a.JSONVal, b.JSONVal)
|
||||
}
|
||||
|
||||
// EqualsRefOfJSONStorageFreeExpr does deep equals between the two objects.
|
||||
func EqualsRefOfJSONStorageFreeExpr(a, b *JSONStorageFreeExpr) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
return EqualsExpr(a.JSONVal, b.JSONVal)
|
||||
}
|
||||
|
||||
// EqualsRefOfJSONStorageSizeExpr does deep equals between the two objects.
|
||||
func EqualsRefOfJSONStorageSizeExpr(a, b *JSONStorageSizeExpr) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
return EqualsExpr(a.JSONVal, b.JSONVal)
|
||||
}
|
||||
|
||||
// EqualsRefOfJoinCondition does deep equals between the two objects.
|
||||
func EqualsRefOfJoinCondition(a, b *JoinCondition) bool {
|
||||
if a == b {
|
||||
|
@ -3165,6 +3216,24 @@ func EqualsCallable(inA, inB Callable) bool {
|
|||
return false
|
||||
}
|
||||
return EqualsRefOfGroupConcatExpr(a, b)
|
||||
case *JSONPrettyExpr:
|
||||
b, ok := inB.(*JSONPrettyExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return EqualsRefOfJSONPrettyExpr(a, b)
|
||||
case *JSONStorageFreeExpr:
|
||||
b, ok := inB.(*JSONStorageFreeExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return EqualsRefOfJSONStorageFreeExpr(a, b)
|
||||
case *JSONStorageSizeExpr:
|
||||
b, ok := inB.(*JSONStorageSizeExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return EqualsRefOfJSONStorageSizeExpr(a, b)
|
||||
case *MatchExpr:
|
||||
b, ok := inB.(*MatchExpr)
|
||||
if !ok {
|
||||
|
@ -3552,6 +3621,24 @@ func EqualsExpr(inA, inB Expr) bool {
|
|||
return false
|
||||
}
|
||||
return EqualsRefOfIsExpr(a, b)
|
||||
case *JSONPrettyExpr:
|
||||
b, ok := inB.(*JSONPrettyExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return EqualsRefOfJSONPrettyExpr(a, b)
|
||||
case *JSONStorageFreeExpr:
|
||||
b, ok := inB.(*JSONStorageFreeExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return EqualsRefOfJSONStorageFreeExpr(a, b)
|
||||
case *JSONStorageSizeExpr:
|
||||
b, ok := inB.(*JSONStorageSizeExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return EqualsRefOfJSONStorageSizeExpr(a, b)
|
||||
case ListArg:
|
||||
b, ok := inB.(ListArg)
|
||||
if !ok {
|
||||
|
|
|
@ -1321,6 +1321,24 @@ func (node *ValuesFuncExpr) Format(buf *TrackedBuffer) {
|
|||
buf.astPrintf(node, "values(%v)", node.Name)
|
||||
}
|
||||
|
||||
// Format formats the node
|
||||
func (node *JSONPrettyExpr) Format(buf *TrackedBuffer) {
|
||||
buf.astPrintf(node, "json_pretty(%v)", node.JSONVal)
|
||||
|
||||
}
|
||||
|
||||
// Format formats the node
|
||||
func (node *JSONStorageFreeExpr) Format(buf *TrackedBuffer) {
|
||||
buf.astPrintf(node, "json_storage_free(%v)", node.JSONVal)
|
||||
|
||||
}
|
||||
|
||||
// Format formats the node
|
||||
func (node *JSONStorageSizeExpr) Format(buf *TrackedBuffer) {
|
||||
buf.astPrintf(node, "json_storage_size(%v)", node.JSONVal)
|
||||
|
||||
}
|
||||
|
||||
// Format formats the node.
|
||||
func (node *SubstrExpr) Format(buf *TrackedBuffer) {
|
||||
if node.To == nil {
|
||||
|
|
|
@ -1761,6 +1761,30 @@ func (node *ValuesFuncExpr) formatFast(buf *TrackedBuffer) {
|
|||
buf.WriteByte(')')
|
||||
}
|
||||
|
||||
// formatFast formats the node
|
||||
func (node *JSONPrettyExpr) formatFast(buf *TrackedBuffer) {
|
||||
buf.WriteString("json_pretty(")
|
||||
buf.printExpr(node, node.JSONVal, true)
|
||||
buf.WriteByte(')')
|
||||
|
||||
}
|
||||
|
||||
// formatFast formats the node
|
||||
func (node *JSONStorageFreeExpr) formatFast(buf *TrackedBuffer) {
|
||||
buf.WriteString("json_storage_free(")
|
||||
buf.printExpr(node, node.JSONVal, true)
|
||||
buf.WriteByte(')')
|
||||
|
||||
}
|
||||
|
||||
// formatFast formats the node
|
||||
func (node *JSONStorageSizeExpr) formatFast(buf *TrackedBuffer) {
|
||||
buf.WriteString("json_storage_size(")
|
||||
buf.printExpr(node, node.JSONVal, true)
|
||||
buf.WriteByte(')')
|
||||
|
||||
}
|
||||
|
||||
// formatFast formats the node.
|
||||
func (node *SubstrExpr) formatFast(buf *TrackedBuffer) {
|
||||
if node.To == nil {
|
||||
|
|
|
@ -172,6 +172,12 @@ func (a *application) rewriteSQLNode(parent SQLNode, node SQLNode, replacer repl
|
|||
return a.rewriteRefOfIsExpr(parent, node, replacer)
|
||||
case IsolationLevel:
|
||||
return a.rewriteIsolationLevel(parent, node, replacer)
|
||||
case *JSONPrettyExpr:
|
||||
return a.rewriteRefOfJSONPrettyExpr(parent, node, replacer)
|
||||
case *JSONStorageFreeExpr:
|
||||
return a.rewriteRefOfJSONStorageFreeExpr(parent, node, replacer)
|
||||
case *JSONStorageSizeExpr:
|
||||
return a.rewriteRefOfJSONStorageSizeExpr(parent, node, replacer)
|
||||
case *JoinCondition:
|
||||
return a.rewriteRefOfJoinCondition(parent, node, replacer)
|
||||
case *JoinTableExpr:
|
||||
|
@ -2649,6 +2655,87 @@ func (a *application) rewriteRefOfIsExpr(parent SQLNode, node *IsExpr, replacer
|
|||
}
|
||||
return true
|
||||
}
|
||||
func (a *application) rewriteRefOfJSONPrettyExpr(parent SQLNode, node *JSONPrettyExpr, replacer replacerFunc) bool {
|
||||
if node == nil {
|
||||
return true
|
||||
}
|
||||
if a.pre != nil {
|
||||
a.cur.replacer = replacer
|
||||
a.cur.parent = parent
|
||||
a.cur.node = node
|
||||
if !a.pre(&a.cur) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if !a.rewriteExpr(node, node.JSONVal, func(newNode, parent SQLNode) {
|
||||
parent.(*JSONPrettyExpr).JSONVal = newNode.(Expr)
|
||||
}) {
|
||||
return false
|
||||
}
|
||||
if a.post != nil {
|
||||
a.cur.replacer = replacer
|
||||
a.cur.parent = parent
|
||||
a.cur.node = node
|
||||
if !a.post(&a.cur) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (a *application) rewriteRefOfJSONStorageFreeExpr(parent SQLNode, node *JSONStorageFreeExpr, replacer replacerFunc) bool {
|
||||
if node == nil {
|
||||
return true
|
||||
}
|
||||
if a.pre != nil {
|
||||
a.cur.replacer = replacer
|
||||
a.cur.parent = parent
|
||||
a.cur.node = node
|
||||
if !a.pre(&a.cur) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if !a.rewriteExpr(node, node.JSONVal, func(newNode, parent SQLNode) {
|
||||
parent.(*JSONStorageFreeExpr).JSONVal = newNode.(Expr)
|
||||
}) {
|
||||
return false
|
||||
}
|
||||
if a.post != nil {
|
||||
a.cur.replacer = replacer
|
||||
a.cur.parent = parent
|
||||
a.cur.node = node
|
||||
if !a.post(&a.cur) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (a *application) rewriteRefOfJSONStorageSizeExpr(parent SQLNode, node *JSONStorageSizeExpr, replacer replacerFunc) bool {
|
||||
if node == nil {
|
||||
return true
|
||||
}
|
||||
if a.pre != nil {
|
||||
a.cur.replacer = replacer
|
||||
a.cur.parent = parent
|
||||
a.cur.node = node
|
||||
if !a.pre(&a.cur) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if !a.rewriteExpr(node, node.JSONVal, func(newNode, parent SQLNode) {
|
||||
parent.(*JSONStorageSizeExpr).JSONVal = newNode.(Expr)
|
||||
}) {
|
||||
return false
|
||||
}
|
||||
if a.post != nil {
|
||||
a.cur.replacer = replacer
|
||||
a.cur.parent = parent
|
||||
a.cur.node = node
|
||||
if !a.post(&a.cur) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (a *application) rewriteRefOfJoinCondition(parent SQLNode, node *JoinCondition, replacer replacerFunc) bool {
|
||||
if node == nil {
|
||||
return true
|
||||
|
@ -5441,6 +5528,12 @@ func (a *application) rewriteCallable(parent SQLNode, node Callable, replacer re
|
|||
return a.rewriteRefOfFuncExpr(parent, node, replacer)
|
||||
case *GroupConcatExpr:
|
||||
return a.rewriteRefOfGroupConcatExpr(parent, node, replacer)
|
||||
case *JSONPrettyExpr:
|
||||
return a.rewriteRefOfJSONPrettyExpr(parent, node, replacer)
|
||||
case *JSONStorageFreeExpr:
|
||||
return a.rewriteRefOfJSONStorageFreeExpr(parent, node, replacer)
|
||||
case *JSONStorageSizeExpr:
|
||||
return a.rewriteRefOfJSONStorageSizeExpr(parent, node, replacer)
|
||||
case *MatchExpr:
|
||||
return a.rewriteRefOfMatchExpr(parent, node, replacer)
|
||||
case *SubstrExpr:
|
||||
|
@ -5605,6 +5698,12 @@ func (a *application) rewriteExpr(parent SQLNode, node Expr, replacer replacerFu
|
|||
return a.rewriteRefOfIntroducerExpr(parent, node, replacer)
|
||||
case *IsExpr:
|
||||
return a.rewriteRefOfIsExpr(parent, node, replacer)
|
||||
case *JSONPrettyExpr:
|
||||
return a.rewriteRefOfJSONPrettyExpr(parent, node, replacer)
|
||||
case *JSONStorageFreeExpr:
|
||||
return a.rewriteRefOfJSONStorageFreeExpr(parent, node, replacer)
|
||||
case *JSONStorageSizeExpr:
|
||||
return a.rewriteRefOfJSONStorageSizeExpr(parent, node, replacer)
|
||||
case ListArg:
|
||||
return a.rewriteListArg(parent, node, replacer)
|
||||
case *Literal:
|
||||
|
|
|
@ -172,6 +172,12 @@ func VisitSQLNode(in SQLNode, f Visit) error {
|
|||
return VisitRefOfIsExpr(in, f)
|
||||
case IsolationLevel:
|
||||
return VisitIsolationLevel(in, f)
|
||||
case *JSONPrettyExpr:
|
||||
return VisitRefOfJSONPrettyExpr(in, f)
|
||||
case *JSONStorageFreeExpr:
|
||||
return VisitRefOfJSONStorageFreeExpr(in, f)
|
||||
case *JSONStorageSizeExpr:
|
||||
return VisitRefOfJSONStorageSizeExpr(in, f)
|
||||
case *JoinCondition:
|
||||
return VisitRefOfJoinCondition(in, f)
|
||||
case *JoinTableExpr:
|
||||
|
@ -1398,6 +1404,42 @@ func VisitRefOfIsExpr(in *IsExpr, f Visit) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func VisitRefOfJSONPrettyExpr(in *JSONPrettyExpr, f Visit) error {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
if cont, err := f(in); err != nil || !cont {
|
||||
return err
|
||||
}
|
||||
if err := VisitExpr(in.JSONVal, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func VisitRefOfJSONStorageFreeExpr(in *JSONStorageFreeExpr, f Visit) error {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
if cont, err := f(in); err != nil || !cont {
|
||||
return err
|
||||
}
|
||||
if err := VisitExpr(in.JSONVal, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func VisitRefOfJSONStorageSizeExpr(in *JSONStorageSizeExpr, f Visit) error {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
if cont, err := f(in); err != nil || !cont {
|
||||
return err
|
||||
}
|
||||
if err := VisitExpr(in.JSONVal, f); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func VisitRefOfJoinCondition(in *JoinCondition, f Visit) error {
|
||||
if in == nil {
|
||||
return nil
|
||||
|
@ -2666,6 +2708,12 @@ func VisitCallable(in Callable, f Visit) error {
|
|||
return VisitRefOfFuncExpr(in, f)
|
||||
case *GroupConcatExpr:
|
||||
return VisitRefOfGroupConcatExpr(in, f)
|
||||
case *JSONPrettyExpr:
|
||||
return VisitRefOfJSONPrettyExpr(in, f)
|
||||
case *JSONStorageFreeExpr:
|
||||
return VisitRefOfJSONStorageFreeExpr(in, f)
|
||||
case *JSONStorageSizeExpr:
|
||||
return VisitRefOfJSONStorageSizeExpr(in, f)
|
||||
case *MatchExpr:
|
||||
return VisitRefOfMatchExpr(in, f)
|
||||
case *SubstrExpr:
|
||||
|
@ -2830,6 +2878,12 @@ func VisitExpr(in Expr, f Visit) error {
|
|||
return VisitRefOfIntroducerExpr(in, f)
|
||||
case *IsExpr:
|
||||
return VisitRefOfIsExpr(in, f)
|
||||
case *JSONPrettyExpr:
|
||||
return VisitRefOfJSONPrettyExpr(in, f)
|
||||
case *JSONStorageFreeExpr:
|
||||
return VisitRefOfJSONStorageFreeExpr(in, f)
|
||||
case *JSONStorageSizeExpr:
|
||||
return VisitRefOfJSONStorageSizeExpr(in, f)
|
||||
case ListArg:
|
||||
return VisitListArg(in, f)
|
||||
case *Literal:
|
||||
|
|
|
@ -1377,6 +1377,48 @@ func (cached *IsExpr) CachedSize(alloc bool) int64 {
|
|||
}
|
||||
return size
|
||||
}
|
||||
func (cached *JSONPrettyExpr) CachedSize(alloc bool) int64 {
|
||||
if cached == nil {
|
||||
return int64(0)
|
||||
}
|
||||
size := int64(0)
|
||||
if alloc {
|
||||
size += int64(16)
|
||||
}
|
||||
// field JSONVal vitess.io/vitess/go/vt/sqlparser.Expr
|
||||
if cc, ok := cached.JSONVal.(cachedObject); ok {
|
||||
size += cc.CachedSize(true)
|
||||
}
|
||||
return size
|
||||
}
|
||||
func (cached *JSONStorageFreeExpr) CachedSize(alloc bool) int64 {
|
||||
if cached == nil {
|
||||
return int64(0)
|
||||
}
|
||||
size := int64(0)
|
||||
if alloc {
|
||||
size += int64(16)
|
||||
}
|
||||
// field JSONVal vitess.io/vitess/go/vt/sqlparser.Expr
|
||||
if cc, ok := cached.JSONVal.(cachedObject); ok {
|
||||
size += cc.CachedSize(true)
|
||||
}
|
||||
return size
|
||||
}
|
||||
func (cached *JSONStorageSizeExpr) CachedSize(alloc bool) int64 {
|
||||
if cached == nil {
|
||||
return int64(0)
|
||||
}
|
||||
size := int64(0)
|
||||
if alloc {
|
||||
size += int64(16)
|
||||
}
|
||||
// field JSONVal vitess.io/vitess/go/vt/sqlparser.Expr
|
||||
if cc, ok := cached.JSONVal.(cachedObject); ok {
|
||||
size += cc.CachedSize(true)
|
||||
}
|
||||
return size
|
||||
}
|
||||
func (cached *JoinCondition) CachedSize(alloc bool) int64 {
|
||||
if cached == nil {
|
||||
return int64(0)
|
||||
|
|
|
@ -317,6 +317,9 @@ var keywords = []keyword{
|
|||
{"invoker", INVOKER},
|
||||
{"join", JOIN},
|
||||
{"json", JSON},
|
||||
{"json_pretty", JSON_PRETTY},
|
||||
{"json_storage_size", JSON_STORAGE_SIZE},
|
||||
{"json_storage_free", JSON_STORAGE_FREE},
|
||||
{"json_table", UNUSED},
|
||||
{"key", KEY},
|
||||
{"keys", KEYS},
|
||||
|
|
|
@ -2296,6 +2296,42 @@ var (
|
|||
}, {
|
||||
input: "create table unused_reserved_keywords (dense_rank bigint, lead VARCHAR(255), percent_rank decimal(3, 0), row TINYINT, rows CHAR(10), constraint PK_project PRIMARY KEY (dense_rank))",
|
||||
output: "create table unused_reserved_keywords (\n\t`dense_rank` bigint,\n\t`lead` VARCHAR(255),\n\t`percent_rank` decimal(3,0),\n\t`row` TINYINT,\n\t`rows` CHAR(10),\n\tconstraint PK_project PRIMARY KEY (`dense_rank`)\n)",
|
||||
}, {
|
||||
input: `SELECT JSON_PRETTY('{"a":"10","b":"15","x":"25"}')`,
|
||||
output: `select json_pretty('{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`,
|
||||
}, {
|
||||
input: `SELECT JSON_PRETTY(N'{"a":"10","b":"15","x":"25"}')`,
|
||||
output: `select json_pretty(N'{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`,
|
||||
}, {
|
||||
input: "SELECT jcol, JSON_PRETTY(jcol) from jtable",
|
||||
output: "select jcol, json_pretty(jcol) from jtable",
|
||||
}, {
|
||||
input: "SELECT JSON_PRETTY(@j)",
|
||||
output: "select json_pretty(@j) from dual",
|
||||
}, {
|
||||
input: "SELECT jcol, JSON_STORAGE_SIZE(jcol) AS Size FROM jtable",
|
||||
output: "select jcol, json_storage_size(jcol) as Size from jtable",
|
||||
}, {
|
||||
input: `SELECT jcol, JSON_STORAGE_SIZE(N'{"a":"10","b":"15","x":"25"}') AS Size FROM jtable`,
|
||||
output: `select jcol, json_storage_size(N'{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') as Size from jtable`,
|
||||
}, {
|
||||
input: `SELECT JSON_STORAGE_SIZE('[100, "sakila", [1, 3, 5], 425.05]') AS A, JSON_STORAGE_SIZE('{"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"}') AS B, JSON_STORAGE_SIZE('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}') AS C,JSON_STORAGE_SIZE('[100, "json", [[10, 20, 30], 3, 5], 425.05]') AS D`,
|
||||
output: `select json_storage_size('[100, \"sakila\", [1, 3, 5], 425.05]') as A, json_storage_size('{\"a\": 1000, \"b\": \"a\", \"c\": \"[1, 3, 5, 7]\"}') as B, json_storage_size('{\"a\": 1000, \"b\": \"wxyz\", \"c\": \"[1, 3, 5, 7]\"}') as C, json_storage_size('[100, \"json\", [[10, 20, 30], 3, 5], 425.05]') as D from dual`,
|
||||
}, {
|
||||
input: "SELECT JSON_STORAGE_SIZE(@j)",
|
||||
output: "select json_storage_size(@j) from dual",
|
||||
}, {
|
||||
input: "SELECT JSON_STORAGE_FREE(jcol) FROM jtable",
|
||||
output: "select json_storage_free(jcol) from jtable",
|
||||
}, {
|
||||
input: `SELECT JSON_STORAGE_FREE('{"a":"10","b":"15","x":"25"}')`,
|
||||
output: `select json_storage_free('{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`,
|
||||
}, {
|
||||
input: `SELECT JSON_STORAGE_FREE(N'{"a":"10","b":"15","x":"25"}')`,
|
||||
output: `select json_storage_free(N'{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`,
|
||||
}, {
|
||||
input: "SELECT JSON_STORAGE_FREE(@j)",
|
||||
output: "select json_storage_free(@j) from dual",
|
||||
}, {
|
||||
input: "SELECT LTRIM('abc')",
|
||||
output: "select ltrim('abc') from dual",
|
||||
|
@ -2435,6 +2471,9 @@ func TestInvalid(t *testing.T) {
|
|||
}, {
|
||||
input: "select 1, next value from seq",
|
||||
err: "syntax error",
|
||||
}, {
|
||||
input: "SELECT jcol, JSON_PRETTY(jcol, jcol) from jtable",
|
||||
err: "syntax error at position 31",
|
||||
}, {
|
||||
input: "select from t1, lateral (with qn as (select t1.a) select (select max(a) from qn)) as dt",
|
||||
err: "syntax error at position 12 near 'from'",
|
||||
|
|
12457
go/vt/sqlparser/sql.go
12457
go/vt/sqlparser/sql.go
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -191,6 +191,7 @@ func bindVariable(yylex yyLexer, bvar string) {
|
|||
%left <str> SUBQUERY_AS_EXPR
|
||||
%left <str> '(' ',' ')'
|
||||
%token <str> ID AT_ID AT_AT_ID HEX STRING NCHAR_STRING INTEGRAL FLOAT DECIMAL HEXNUM VALUE_ARG LIST_ARG COMMENT COMMENT_KEYWORD BIT_LITERAL COMPRESSION
|
||||
%token <str> JSON_PRETTY JSON_STORAGE_SIZE JSON_STORAGE_FREE
|
||||
%token <str> EXTRACT
|
||||
%token <str> NULL TRUE FALSE OFF
|
||||
%token <str> DISCARD IMPORT ENABLE DISABLE TABLESPACE
|
||||
|
@ -4744,6 +4745,18 @@ UTC_DATE func_paren_opt
|
|||
{
|
||||
$$ = &WeightStringFuncExpr{Expr: $3, As: $4}
|
||||
}
|
||||
| JSON_PRETTY openb expression closeb
|
||||
{
|
||||
$$ = &JSONPrettyExpr{JSONVal: $3}
|
||||
}
|
||||
| JSON_STORAGE_FREE openb expression closeb
|
||||
{
|
||||
$$ = &JSONStorageFreeExpr{ JSONVal: $3}
|
||||
}
|
||||
| JSON_STORAGE_SIZE openb expression closeb
|
||||
{
|
||||
$$ = &JSONStorageSizeExpr{ JSONVal: $3}
|
||||
}
|
||||
| LTRIM openb expression closeb
|
||||
{
|
||||
$$ = &TrimFuncExpr{TrimFuncType:LTrimType, StringArg: $3}
|
||||
|
@ -6019,6 +6032,9 @@ non_reserved_keyword:
|
|||
| INDEXES
|
||||
| ISOLATION
|
||||
| JSON
|
||||
| JSON_PRETTY
|
||||
| JSON_STORAGE_FREE
|
||||
| JSON_STORAGE_SIZE
|
||||
| KEY_BLOCK_SIZE
|
||||
| KEYS
|
||||
| KEYSPACES
|
||||
|
|
|
@ -2946,3 +2946,22 @@ Gen4 plan same as above
|
|||
}
|
||||
}
|
||||
Gen4 plan same as above
|
||||
|
||||
# json utility functions
|
||||
"select jcol, JSON_STORAGE_SIZE(jcol), JSON_STORAGE_FREE(jcol), JSON_PRETTY(jcol) from user"
|
||||
{
|
||||
"QueryType": "SELECT",
|
||||
"Original": "select jcol, JSON_STORAGE_SIZE(jcol), JSON_STORAGE_FREE(jcol), JSON_PRETTY(jcol) from user",
|
||||
"Instructions": {
|
||||
"OperatorType": "Route",
|
||||
"Variant": "Scatter",
|
||||
"Keyspace": {
|
||||
"Name": "user",
|
||||
"Sharded": true
|
||||
},
|
||||
"FieldQuery": "select jcol, json_storage_size(jcol), json_storage_free(jcol), json_pretty(jcol) from `user` where 1 != 1",
|
||||
"Query": "select jcol, json_storage_size(jcol), json_storage_free(jcol), json_pretty(jcol) from `user`",
|
||||
"Table": "`user`"
|
||||
}
|
||||
}
|
||||
Gen4 plan same as above
|
||||
|
|
|
@ -20,7 +20,7 @@ fi
|
|||
|
||||
mv $CUR $TMP
|
||||
output=$(go run ./goyacc -fast-append -o $CUR sql.y)
|
||||
expectedOutput=$'\nconflicts: 5 shift/reduce'
|
||||
expectedOutput=$'\nconflicts: 8 shift/reduce'
|
||||
|
||||
if [[ "$output" != "$expectedOutput" ]]; then
|
||||
echo -e "Expected output from goyacc:$expectedOutput\ngot:$output"
|
||||
|
|
Загрузка…
Ссылка в новой задаче