storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/s3select/sql/utils.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2019 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package sql
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  )
    23  
    24  // String functions
    25  
    26  // String - returns the JSONPath representation
    27  func (e *JSONPath) String() string {
    28  	if len(e.pathString) == 0 {
    29  		parts := make([]string, len(e.PathExpr)+1)
    30  		parts[0] = e.BaseKey.String()
    31  		for i, pe := range e.PathExpr {
    32  			parts[i+1] = pe.String()
    33  		}
    34  		e.pathString = strings.Join(parts, "")
    35  	}
    36  	return e.pathString
    37  }
    38  
    39  // StripTableAlias removes a table alias from the path. The result is also
    40  // cached for repeated lookups during SQL query evaluation.
    41  func (e *JSONPath) StripTableAlias(tableAlias string) []*JSONPathElement {
    42  	if e.strippedTableAlias == tableAlias {
    43  		return e.strippedPathExpr
    44  	}
    45  
    46  	hasTableAlias := e.BaseKey.String() == tableAlias || strings.ToLower(e.BaseKey.String()) == baseTableName
    47  	var pathExpr []*JSONPathElement
    48  	if hasTableAlias {
    49  		pathExpr = e.PathExpr
    50  	} else {
    51  		pathExpr = make([]*JSONPathElement, len(e.PathExpr)+1)
    52  		pathExpr[0] = &JSONPathElement{Key: &ObjectKey{ID: e.BaseKey}}
    53  		copy(pathExpr[1:], e.PathExpr)
    54  	}
    55  	e.strippedTableAlias = tableAlias
    56  	e.strippedPathExpr = pathExpr
    57  	return e.strippedPathExpr
    58  }
    59  
    60  func (e *JSONPathElement) String() string {
    61  	switch {
    62  	case e.Key != nil:
    63  		return e.Key.String()
    64  	case e.Index != nil:
    65  		return fmt.Sprintf("[%d]", *e.Index)
    66  	case e.ObjectWildcard:
    67  		return ".*"
    68  	case e.ArrayWildcard:
    69  		return "[*]"
    70  	}
    71  	return ""
    72  }
    73  
    74  // String removes double quotes in quoted identifiers
    75  func (i *Identifier) String() string {
    76  	if i.Unquoted != nil {
    77  		return *i.Unquoted
    78  	}
    79  	return string(*i.Quoted)
    80  }
    81  
    82  func (o *ObjectKey) String() string {
    83  	if o.Lit != nil {
    84  		return fmt.Sprintf("['%s']", string(*o.Lit))
    85  	}
    86  	return fmt.Sprintf(".%s", o.ID.String())
    87  }
    88  
    89  func (o *ObjectKey) keyString() string {
    90  	if o.Lit != nil {
    91  		return string(*o.Lit)
    92  	}
    93  	return o.ID.String()
    94  }
    95  
    96  // getLastKeypathComponent checks if the given expression is a path
    97  // expression, and if so extracts the last dot separated component of
    98  // the path. Otherwise it returns false.
    99  func getLastKeypathComponent(e *Expression) (string, bool) {
   100  	if len(e.And) > 1 ||
   101  		len(e.And[0].Condition) > 1 ||
   102  		e.And[0].Condition[0].Not != nil ||
   103  		e.And[0].Condition[0].Operand.ConditionRHS != nil {
   104  		return "", false
   105  	}
   106  
   107  	operand := e.And[0].Condition[0].Operand.Operand
   108  	if operand.Right != nil ||
   109  		operand.Left.Right != nil ||
   110  		operand.Left.Left.Negated != nil ||
   111  		operand.Left.Left.Primary.JPathExpr == nil {
   112  		return "", false
   113  	}
   114  
   115  	// Check if path expression ends in a key
   116  	jpath := operand.Left.Left.Primary.JPathExpr
   117  	n := len(jpath.PathExpr)
   118  	if n > 0 && jpath.PathExpr[n-1].Key == nil {
   119  		return "", false
   120  	}
   121  	ps := jpath.String()
   122  	if idx := strings.LastIndex(ps, "."); idx >= 0 {
   123  		// Get last part of path string.
   124  		ps = ps[idx+1:]
   125  	}
   126  	return ps, true
   127  }
   128  
   129  // HasKeypath returns if the from clause has a key path -
   130  // e.g. S3object[*].id
   131  func (from *TableExpression) HasKeypath() bool {
   132  	return len(from.Table.PathExpr) > 1
   133  }