github.com/mithrandie/csvq@v1.18.1/lib/query/inline_tables_test.go (about) 1 package query 2 3 import ( 4 "context" 5 "reflect" 6 "testing" 7 8 "github.com/mithrandie/csvq/lib/parser" 9 "github.com/mithrandie/csvq/lib/value" 10 ) 11 12 var inlineTableMapSetTests = []struct { 13 Name string 14 Expr parser.InlineTable 15 Result InlineTableMap 16 Error string 17 }{ 18 { 19 Name: "InlineTableMap Set", 20 Expr: parser.InlineTable{ 21 Name: parser.Identifier{Literal: "it"}, 22 Fields: []parser.QueryExpression{ 23 parser.Identifier{Literal: "c1"}, 24 parser.Identifier{Literal: "c2"}, 25 parser.Identifier{Literal: "num"}, 26 }, 27 Query: parser.SelectQuery{ 28 SelectEntity: parser.SelectEntity{ 29 SelectClause: parser.SelectClause{ 30 Fields: []parser.QueryExpression{ 31 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 32 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 33 parser.Field{Object: parser.NewIntegerValueFromString("1")}, 34 }, 35 }, 36 FromClause: parser.FromClause{ 37 Tables: []parser.QueryExpression{ 38 parser.Table{Object: parser.Identifier{Literal: "table1"}}, 39 }, 40 }, 41 }, 42 }, 43 }, 44 Result: InlineTableMap{ 45 "IT": &View{ 46 Header: NewHeader("it", []string{"c1", "c2", "num"}), 47 RecordSet: []Record{ 48 NewRecord([]value.Primary{ 49 value.NewString("1"), 50 value.NewString("str1"), 51 value.NewInteger(1), 52 }), 53 NewRecord([]value.Primary{ 54 value.NewString("2"), 55 value.NewString("str2"), 56 value.NewInteger(1), 57 }), 58 NewRecord([]value.Primary{ 59 value.NewString("3"), 60 value.NewString("str3"), 61 value.NewInteger(1), 62 }), 63 }, 64 }, 65 }, 66 }, 67 { 68 Name: "InlineTableMap Set Recursive Table", 69 Expr: parser.InlineTable{ 70 Recursive: parser.Token{Token: parser.RECURSIVE, Literal: "recursive"}, 71 Name: parser.Identifier{Literal: "it_recursive"}, 72 Fields: []parser.QueryExpression{ 73 parser.Identifier{Literal: "n"}, 74 }, 75 Query: parser.SelectQuery{ 76 SelectEntity: parser.SelectSet{ 77 LHS: parser.SelectEntity{ 78 SelectClause: parser.SelectClause{ 79 Fields: []parser.QueryExpression{ 80 parser.Field{Object: parser.NewIntegerValueFromString("1")}, 81 }, 82 }, 83 }, 84 Operator: parser.Token{Token: parser.UNION, Literal: "union"}, 85 RHS: parser.SelectEntity{ 86 SelectClause: parser.SelectClause{ 87 Fields: []parser.QueryExpression{ 88 parser.Field{ 89 Object: parser.Arithmetic{ 90 LHS: parser.FieldReference{Column: parser.Identifier{Literal: "n"}}, 91 RHS: parser.NewIntegerValueFromString("1"), 92 Operator: parser.Token{Token: '+', Literal: "+"}, 93 }, 94 }, 95 }, 96 }, 97 FromClause: parser.FromClause{ 98 Tables: []parser.QueryExpression{ 99 parser.Table{Object: parser.Identifier{Literal: "it_recursive"}}, 100 }, 101 }, 102 WhereClause: parser.WhereClause{ 103 Filter: parser.Comparison{ 104 LHS: parser.FieldReference{Column: parser.Identifier{Literal: "n"}}, 105 RHS: parser.NewIntegerValueFromString("3"), 106 Operator: parser.Token{Token: '<', Literal: "<"}, 107 }, 108 }, 109 }, 110 }, 111 }, 112 }, 113 Result: InlineTableMap{ 114 "IT": &View{ 115 Header: NewHeader("it", []string{"c1", "c2", "num"}), 116 RecordSet: []Record{ 117 NewRecord([]value.Primary{ 118 value.NewString("1"), 119 value.NewString("str1"), 120 value.NewInteger(1), 121 }), 122 NewRecord([]value.Primary{ 123 value.NewString("2"), 124 value.NewString("str2"), 125 value.NewInteger(1), 126 }), 127 NewRecord([]value.Primary{ 128 value.NewString("3"), 129 value.NewString("str3"), 130 value.NewInteger(1), 131 }), 132 }, 133 }, 134 "IT_RECURSIVE": &View{ 135 Header: []HeaderField{ 136 { 137 View: "it_recursive", 138 Column: "n", 139 Number: 1, 140 IsFromTable: true, 141 }, 142 }, 143 RecordSet: []Record{ 144 NewRecord([]value.Primary{ 145 value.NewInteger(1), 146 }), 147 NewRecord([]value.Primary{ 148 value.NewInteger(2), 149 }), 150 NewRecord([]value.Primary{ 151 value.NewInteger(3), 152 }), 153 }, 154 }, 155 }, 156 }, 157 { 158 Name: "InlineTableMap Set Redefined Error", 159 Expr: parser.InlineTable{ 160 Name: parser.Identifier{Literal: "it"}, 161 Fields: []parser.QueryExpression{ 162 parser.Identifier{Literal: "c1"}, 163 parser.Identifier{Literal: "c2"}, 164 }, 165 Query: parser.SelectQuery{ 166 SelectEntity: parser.SelectEntity{ 167 SelectClause: parser.SelectClause{ 168 Fields: []parser.QueryExpression{ 169 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 170 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 171 }, 172 }, 173 FromClause: parser.FromClause{ 174 Tables: []parser.QueryExpression{ 175 parser.Table{Object: parser.Identifier{Literal: "table1"}}, 176 }, 177 }, 178 }, 179 }, 180 }, 181 Error: "inline table it is redefined", 182 }, 183 { 184 Name: "InlineTableMap Set Query Error", 185 Expr: parser.InlineTable{ 186 Name: parser.Identifier{Literal: "it2"}, 187 Fields: []parser.QueryExpression{ 188 parser.Identifier{Literal: "c1"}, 189 parser.Identifier{Literal: "c2"}, 190 }, 191 Query: parser.SelectQuery{ 192 SelectEntity: parser.SelectEntity{ 193 SelectClause: parser.SelectClause{ 194 Fields: []parser.QueryExpression{ 195 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 196 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}}, 197 }, 198 }, 199 FromClause: parser.FromClause{ 200 Tables: []parser.QueryExpression{ 201 parser.Table{Object: parser.Identifier{Literal: "table1"}}, 202 }, 203 }, 204 }, 205 }, 206 }, 207 Error: "field notexist does not exist", 208 }, 209 { 210 Name: "InlineTableMap Set Field Length Error", 211 Expr: parser.InlineTable{ 212 Name: parser.Identifier{Literal: "it2"}, 213 Fields: []parser.QueryExpression{ 214 parser.Identifier{Literal: "c1"}, 215 }, 216 Query: parser.SelectQuery{ 217 SelectEntity: parser.SelectEntity{ 218 SelectClause: parser.SelectClause{ 219 Fields: []parser.QueryExpression{ 220 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 221 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 222 }, 223 }, 224 FromClause: parser.FromClause{ 225 Tables: []parser.QueryExpression{ 226 parser.Table{Object: parser.Identifier{Literal: "table1"}}, 227 }, 228 }, 229 }, 230 }, 231 }, 232 Error: "select query should return exactly 1 field for inline table it2", 233 }, 234 { 235 Name: "InlineTableMap Set Duplicate Field Name Error", 236 Expr: parser.InlineTable{ 237 Name: parser.Identifier{Literal: "it2"}, 238 Fields: []parser.QueryExpression{ 239 parser.Identifier{Literal: "c1"}, 240 parser.Identifier{Literal: "c1"}, 241 }, 242 Query: parser.SelectQuery{ 243 SelectEntity: parser.SelectEntity{ 244 SelectClause: parser.SelectClause{ 245 Fields: []parser.QueryExpression{ 246 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 247 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 248 }, 249 }, 250 FromClause: parser.FromClause{ 251 Tables: []parser.QueryExpression{ 252 parser.Table{Object: parser.Identifier{Literal: "table1"}}, 253 }, 254 }, 255 }, 256 }, 257 }, 258 Error: "field name c1 is a duplicate", 259 }, 260 } 261 262 func TestInlineTableMap_Set(t *testing.T) { 263 defer func() { 264 _ = TestTx.CachedViews.Clean(TestTx.FileContainer) 265 initFlag(TestTx.Flags) 266 }() 267 268 TestTx.Flags.Repository = TestDataDir 269 270 it := InlineTableMap{} 271 272 scope := NewReferenceScope(TestTx) 273 ctx := context.Background() 274 for _, v := range inlineTableMapSetTests { 275 _ = TestTx.CachedViews.Clean(TestTx.FileContainer) 276 err := it.Set(ctx, scope, v.Expr) 277 if err != nil { 278 if len(v.Error) < 1 { 279 t.Errorf("%s: unexpected error %q", v.Name, err) 280 } else if err.Error() != v.Error { 281 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 282 } 283 continue 284 } 285 if 0 < len(v.Error) { 286 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 287 continue 288 } 289 if !reflect.DeepEqual(it, v.Result) { 290 t.Errorf("%s: result = %v, want %v", v.Name, it, v.Result) 291 } 292 } 293 294 recursiveExpr := parser.InlineTable{ 295 Recursive: parser.Token{Token: parser.RECURSIVE, Literal: "recursive"}, 296 Name: parser.Identifier{Literal: "nested_error"}, 297 Fields: []parser.QueryExpression{ 298 parser.Identifier{Literal: "n"}, 299 }, 300 Query: parser.SelectQuery{}, 301 } 302 scope.RecursiveTable = &recursiveExpr 303 expectErr := "recursive queries are nested" 304 err := it.Set(ctx, scope, recursiveExpr) 305 if err == nil { 306 t.Errorf("no error, want error %q", expectErr) 307 } else if err.Error() != expectErr { 308 t.Errorf("error %q, want error %q", err.Error(), expectErr) 309 } 310 } 311 312 var inlineTableMapGetTests = []struct { 313 Name string 314 TableName parser.Identifier 315 Result *View 316 Error string 317 }{ 318 { 319 Name: "InlineTableMap Get", 320 TableName: parser.Identifier{Literal: "it"}, 321 Result: &View{ 322 Header: NewHeader("it", []string{"c1", "c2", "num"}), 323 RecordSet: []Record{ 324 NewRecord([]value.Primary{ 325 value.NewString("1"), 326 value.NewString("str1"), 327 value.NewInteger(1), 328 }), 329 NewRecord([]value.Primary{ 330 value.NewString("2"), 331 value.NewString("str2"), 332 value.NewInteger(1), 333 }), 334 NewRecord([]value.Primary{ 335 value.NewString("3"), 336 value.NewString("str3"), 337 value.NewInteger(1), 338 }), 339 }, 340 }, 341 }, 342 { 343 Name: "InlineTableMap Get Undefined Error", 344 TableName: parser.Identifier{Literal: "notexist"}, 345 Error: "inline table notexist is undefined", 346 }, 347 } 348 349 func TestInlineTableMap_Get(t *testing.T) { 350 it := InlineTableMap{ 351 "IT": &View{ 352 Header: NewHeader("it", []string{"c1", "c2", "num"}), 353 RecordSet: []Record{ 354 NewRecord([]value.Primary{ 355 value.NewString("1"), 356 value.NewString("str1"), 357 value.NewInteger(1), 358 }), 359 NewRecord([]value.Primary{ 360 value.NewString("2"), 361 value.NewString("str2"), 362 value.NewInteger(1), 363 }), 364 NewRecord([]value.Primary{ 365 value.NewString("3"), 366 value.NewString("str3"), 367 value.NewInteger(1), 368 }), 369 }, 370 }, 371 } 372 373 for _, v := range inlineTableMapGetTests { 374 ret, err := it.Get(v.TableName) 375 if err != nil { 376 if len(v.Error) < 1 { 377 t.Errorf("%s: unexpected error %q", v.Name, err) 378 } else if err.Error() != v.Error { 379 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 380 } 381 continue 382 } 383 if 0 < len(v.Error) { 384 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 385 continue 386 } 387 if !reflect.DeepEqual(ret, v.Result) { 388 t.Errorf("%s: result = %v, want %v", v.Name, ret, v.Result) 389 } 390 } 391 }