|
|
|
/*
|
|
|
|
* MinIO Cloud Storage, (C) 2019 MinIO, Inc.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package sql
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// String functions
|
|
|
|
|
|
|
|
// String - returns the JSONPath representation
|
|
|
|
func (e *JSONPath) String() string {
|
|
|
|
if len(e.pathString) == 0 {
|
|
|
|
parts := make([]string, len(e.PathExpr)+1)
|
|
|
|
parts[0] = e.BaseKey.String()
|
|
|
|
for i, pe := range e.PathExpr {
|
|
|
|
parts[i+1] = pe.String()
|
|
|
|
}
|
|
|
|
e.pathString = strings.Join(parts, "")
|
|
|
|
}
|
|
|
|
return e.pathString
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *JSONPathElement) String() string {
|
|
|
|
switch {
|
|
|
|
case e.Key != nil:
|
|
|
|
return e.Key.String()
|
|
|
|
case e.Index != nil:
|
|
|
|
return fmt.Sprintf("[%d]", *e.Index)
|
|
|
|
case e.ObjectWildcard:
|
|
|
|
return ".*"
|
|
|
|
case e.ArrayWildcard:
|
|
|
|
return "[*]"
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// String removes double quotes in quoted identifiers
|
|
|
|
func (i *Identifier) String() string {
|
|
|
|
if i.Unquoted != nil {
|
|
|
|
return *i.Unquoted
|
|
|
|
}
|
|
|
|
return string(*i.Quoted)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *ObjectKey) String() string {
|
|
|
|
if o.Lit != nil {
|
|
|
|
return fmt.Sprintf("['%s']", string(*o.Lit))
|
|
|
|
}
|
|
|
|
return fmt.Sprintf(".%s", o.ID.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *ObjectKey) keyString() string {
|
|
|
|
if o.Lit != nil {
|
|
|
|
return string(*o.Lit)
|
|
|
|
}
|
|
|
|
return o.ID.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// getLastKeypathComponent checks if the given expression is a path
|
|
|
|
// expression, and if so extracts the last dot separated component of
|
|
|
|
// the path. Otherwise it returns false.
|
|
|
|
func getLastKeypathComponent(e *Expression) (string, bool) {
|
|
|
|
if len(e.And) > 1 ||
|
|
|
|
len(e.And[0].Condition) > 1 ||
|
|
|
|
e.And[0].Condition[0].Not != nil ||
|
|
|
|
e.And[0].Condition[0].Operand.ConditionRHS != nil {
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
|
|
|
|
operand := e.And[0].Condition[0].Operand.Operand
|
|
|
|
if operand.Right != nil ||
|
|
|
|
operand.Left.Right != nil ||
|
|
|
|
operand.Left.Left.Negated != nil ||
|
|
|
|
operand.Left.Left.Primary.JPathExpr == nil {
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if path expression ends in a key
|
|
|
|
jpath := operand.Left.Left.Primary.JPathExpr
|
|
|
|
n := len(jpath.PathExpr)
|
|
|
|
if n > 0 && jpath.PathExpr[n-1].Key == nil {
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
ps := jpath.String()
|
|
|
|
if idx := strings.LastIndex(ps, "."); idx >= 0 {
|
|
|
|
// Get last part of path string.
|
|
|
|
ps = ps[idx+1:]
|
|
|
|
}
|
|
|
|
return ps, true
|
|
|
|
}
|
|
|
|
|
|
|
|
// HasKeypath returns if the from clause has a key path -
|
|
|
|
// e.g. S3object[*].id
|
|
|
|
func (from *TableExpression) HasKeypath() bool {
|
|
|
|
return len(from.Table.PathExpr) > 1
|
|
|
|
}
|