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 }