github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sem/tree/hide_constants.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  //
    11  //
    12  
    13  package tree
    14  
    15  import (
    16  	"fmt"
    17  	"strings"
    18  )
    19  
    20  // formatNodeOrHideConstants recurses into a node for pretty-printing,
    21  // unless hideConstants is set in the flags and the node is a datum or
    22  // a literal.
    23  func (ctx *FmtCtx) formatNodeOrHideConstants(n NodeFormatter) {
    24  	if ctx.flags.HasFlags(FmtHideConstants) {
    25  		switch v := n.(type) {
    26  		case *ValuesClause:
    27  			v.formatHideConstants(ctx)
    28  			return
    29  		case *Tuple:
    30  			v.formatHideConstants(ctx)
    31  			return
    32  		case *Array:
    33  			v.formatHideConstants(ctx)
    34  			return
    35  		case *Placeholder:
    36  			// Placeholders should be printed as placeholder markers.
    37  			// Deliberately empty so we format as normal.
    38  		case Datum, Constant:
    39  			ctx.WriteByte('_')
    40  			return
    41  		}
    42  	}
    43  	n.Format(ctx)
    44  }
    45  
    46  // formatHideConstants shortens multi-valued VALUES clauses to a
    47  // VALUES clause with a single value.
    48  // e.g. VALUES (a,b,c), (d,e,f) -> VALUES (_, _, _), (__more__)
    49  func (node *ValuesClause) formatHideConstants(ctx *FmtCtx) {
    50  	ctx.WriteString("VALUES (")
    51  	node.Rows[0].formatHideConstants(ctx)
    52  	ctx.WriteByte(')')
    53  	if len(node.Rows) > 1 {
    54  		ctx.Printf(", (%s)", arityString(len(node.Rows)-1))
    55  	}
    56  }
    57  
    58  // formatHideConstants is used exclusively by ValuesClause above.
    59  // Other AST that contain Exprs do not use this.
    60  func (node *Exprs) formatHideConstants(ctx *FmtCtx) {
    61  	exprs := *node
    62  	if len(exprs) < 2 {
    63  		node.Format(ctx)
    64  		return
    65  	}
    66  
    67  	// First, determine if there are only literals/placeholders.
    68  	var i int
    69  	for i = 0; i < len(exprs); i++ {
    70  		switch exprs[i].(type) {
    71  		case Datum, Constant, *Placeholder:
    72  			continue
    73  		}
    74  		break
    75  	}
    76  	// If so, then use the special representation.
    77  	if i == len(exprs) {
    78  		// We copy the node to preserve the "row" boolean flag.
    79  		v2 := append(make(Exprs, 0, 3), exprs[:2]...)
    80  		if len(exprs) > 2 {
    81  			v2 = append(v2, arityIndicator(len(exprs)-2))
    82  		}
    83  		v2.Format(ctx)
    84  		return
    85  	}
    86  	node.Format(ctx)
    87  }
    88  
    89  // formatHideConstants formats tuples containing only literals or
    90  // placeholders and longer than 1 element as a tuple of its first
    91  // two elements, scrubbed.
    92  // e.g. (1)               -> (_)
    93  //      (1, 2)            -> (_, _)
    94  //      (1, 2, 3)         -> (_, _, __more3__)
    95  //      ROW()             -> ROW()
    96  //      ROW($1, $2, $3)   -> ROW($1, $2, __more3__)
    97  //      (1+2, 2+3, 3+4)   -> (_ + _, _ + _, _ + _)
    98  //      (1+2, b, c)       -> (_ + _, b, c)
    99  func (node *Tuple) formatHideConstants(ctx *FmtCtx) {
   100  	if len(node.Exprs) < 2 {
   101  		node.Format(ctx)
   102  		return
   103  	}
   104  
   105  	// First, determine if there are only literals/placeholders.
   106  	var i int
   107  	for i = 0; i < len(node.Exprs); i++ {
   108  		switch node.Exprs[i].(type) {
   109  		case Datum, Constant, *Placeholder:
   110  			continue
   111  		}
   112  		break
   113  	}
   114  	// If so, then use the special representation.
   115  	if i == len(node.Exprs) {
   116  		// We copy the node to preserve the "row" boolean flag.
   117  		v2 := *node
   118  		v2.Exprs = append(make(Exprs, 0, 3), v2.Exprs[:2]...)
   119  		if len(node.Exprs) > 2 {
   120  			v2.Exprs = append(v2.Exprs, arityIndicator(len(node.Exprs)-2))
   121  		}
   122  		if node.Labels != nil {
   123  			v2.Labels = node.Labels[:2]
   124  		}
   125  		v2.Format(ctx)
   126  		return
   127  	}
   128  	node.Format(ctx)
   129  }
   130  
   131  // formatHideConstants formats array expressions containing only
   132  // literals or placeholders and longer than 1 element as an array
   133  // expression of its first two elements, scrubbed.
   134  // e.g. array[1]             -> array[_]
   135  //      array[1, 2]          -> array[_, _]
   136  //      array[1, 2, 3]       -> array[_, _, __more3__]
   137  //      array[1+2, 2+3, 3+4] -> array[_ + _, _ + _, _ + _]
   138  func (node *Array) formatHideConstants(ctx *FmtCtx) {
   139  	if len(node.Exprs) < 2 {
   140  		node.Format(ctx)
   141  		return
   142  	}
   143  
   144  	// First, determine if there are only literals/placeholders.
   145  	var i int
   146  	for i = 0; i < len(node.Exprs); i++ {
   147  		switch node.Exprs[i].(type) {
   148  		case Datum, Constant, *Placeholder:
   149  			continue
   150  		}
   151  		break
   152  	}
   153  	// If so, then use the special representation.
   154  	if i == len(node.Exprs) {
   155  		// We copy the node to preserve the "row" boolean flag.
   156  		v2 := *node
   157  		v2.Exprs = append(make(Exprs, 0, 3), v2.Exprs[:2]...)
   158  		if len(node.Exprs) > 2 {
   159  			v2.Exprs = append(v2.Exprs, arityIndicator(len(node.Exprs)-2))
   160  		}
   161  		v2.Format(ctx)
   162  		return
   163  	}
   164  	node.Format(ctx)
   165  }
   166  
   167  func arityIndicator(n int) Expr {
   168  	return NewUnresolvedName(arityString(n))
   169  }
   170  
   171  func arityString(n int) string {
   172  	var v int
   173  	for v = 1; n >= 10; n /= 10 {
   174  		v = v * 10
   175  	}
   176  	v = v * n
   177  	return fmt.Sprintf("__more%d__", v)
   178  }
   179  
   180  func isArityIndicatorString(s string) bool {
   181  	return strings.HasPrefix(s, "__more")
   182  }