github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/s3select/sql/utils.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package sql 19 20 import ( 21 "fmt" 22 "strings" 23 ) 24 25 // String functions 26 27 // String - returns the JSONPath representation 28 func (e *JSONPath) String() string { 29 if len(e.pathString) == 0 { 30 parts := make([]string, len(e.PathExpr)+1) 31 parts[0] = e.BaseKey.String() 32 for i, pe := range e.PathExpr { 33 parts[i+1] = pe.String() 34 } 35 e.pathString = strings.Join(parts, "") 36 } 37 return e.pathString 38 } 39 40 // StripTableAlias removes a table alias from the path. The result is also 41 // cached for repeated lookups during SQL query evaluation. 42 func (e *JSONPath) StripTableAlias(tableAlias string) []*JSONPathElement { 43 if e.strippedTableAlias == tableAlias { 44 return e.strippedPathExpr 45 } 46 47 hasTableAlias := e.BaseKey.String() == tableAlias || strings.EqualFold(e.BaseKey.String(), baseTableName) 48 var pathExpr []*JSONPathElement 49 if hasTableAlias { 50 pathExpr = e.PathExpr 51 } else { 52 pathExpr = make([]*JSONPathElement, len(e.PathExpr)+1) 53 pathExpr[0] = &JSONPathElement{Key: &ObjectKey{ID: e.BaseKey}} 54 copy(pathExpr[1:], e.PathExpr) 55 } 56 e.strippedTableAlias = tableAlias 57 e.strippedPathExpr = pathExpr 58 return e.strippedPathExpr 59 } 60 61 func (e *JSONPathElement) String() string { 62 switch { 63 case e.Key != nil: 64 return e.Key.String() 65 case e.Index != nil: 66 return fmt.Sprintf("[%d]", *e.Index) 67 case e.ObjectWildcard: 68 return ".*" 69 case e.ArrayWildcard: 70 return "[*]" 71 } 72 return "" 73 } 74 75 // String removes double quotes in quoted identifiers 76 func (i *Identifier) String() string { 77 if i.Unquoted != nil { 78 return *i.Unquoted 79 } 80 return string(*i.Quoted) 81 } 82 83 func (o *ObjectKey) String() string { 84 if o.Lit != nil { 85 return fmt.Sprintf("['%s']", string(*o.Lit)) 86 } 87 return fmt.Sprintf(".%s", o.ID.String()) 88 } 89 90 func (o *ObjectKey) keyString() string { 91 if o.Lit != nil { 92 return string(*o.Lit) 93 } 94 return o.ID.String() 95 } 96 97 // getLastKeypathComponent checks if the given expression is a path 98 // expression, and if so extracts the last dot separated component of 99 // the path. Otherwise it returns false. 100 func getLastKeypathComponent(e *Expression) (string, bool) { 101 if len(e.And) > 1 || 102 len(e.And[0].Condition) > 1 || 103 e.And[0].Condition[0].Not != nil || 104 e.And[0].Condition[0].Operand.ConditionRHS != nil { 105 return "", false 106 } 107 108 operand := e.And[0].Condition[0].Operand.Operand 109 if operand.Right != nil || 110 operand.Left.Right != nil || 111 operand.Left.Left.Negated != nil || 112 operand.Left.Left.Primary.JPathExpr == nil { 113 return "", false 114 } 115 116 // Check if path expression ends in a key 117 jpath := operand.Left.Left.Primary.JPathExpr 118 n := len(jpath.PathExpr) 119 if n > 0 && jpath.PathExpr[n-1].Key == nil { 120 return "", false 121 } 122 ps := jpath.String() 123 if idx := strings.LastIndex(ps, "."); idx >= 0 { 124 // Get last part of path string. 125 ps = ps[idx+1:] 126 } 127 return ps, true 128 } 129 130 // HasKeypath returns if the from clause has a key path - 131 // e.g. S3object[*].id 132 func (from *TableExpression) HasKeypath() bool { 133 return len(from.Table.PathExpr) > 1 134 }