@@ -3,6 +3,7 @@ package aql
3
3
import (
4
4
"errors"
5
5
"fmt"
6
+ openapi "github.com/aep/apogy/api/go"
6
7
"strconv"
7
8
"strings"
8
9
"unicode"
@@ -26,6 +27,7 @@ const (
26
27
TOKEN_COMMA
27
28
TOKEN_PARAM // New token type for parameter placeholders
28
29
TOKEN_AND // Logical AND operator (& or &&)
30
+ TOKEN_SKIP // Skip operator ($)
29
31
)
30
32
31
33
func tokenName (i TokenType ) string {
@@ -58,6 +60,8 @@ func tokenName(i TokenType) string {
58
60
return "PARAM"
59
61
case TOKEN_AND :
60
62
return "AND"
63
+ case TOKEN_SKIP :
64
+ return "SKIP"
61
65
}
62
66
return "ILLEGAL"
63
67
}
@@ -155,6 +159,8 @@ func (l *Lexer) NextToken() Token {
155
159
tok = Token {TOKEN_GREATER , string (l .ch )}
156
160
case '^' :
157
161
tok = Token {TOKEN_PREFIX , string (l .ch )}
162
+ case '$' :
163
+ tok = Token {TOKEN_SKIP , string (l .ch )}
158
164
case '(' :
159
165
tok = Token {TOKEN_LPAREN , string (l .ch )}
160
166
case ')' :
@@ -203,7 +209,7 @@ func (l *Lexer) NextToken() Token {
203
209
204
210
type Query struct {
205
211
Type string
206
- Filter map [ string ] interface {}
212
+ Filter []openapi. Filter
207
213
Links []* Query
208
214
}
209
215
@@ -213,30 +219,62 @@ func (q *Query) String() string {
213
219
214
220
if len (q .Filter ) > 0 {
215
221
filters := make ([]string , 0 )
216
- for k , v := range q .Filter {
217
- // Determine operator
222
+ for _ , filter := range q .Filter {
218
223
var operator string = "="
219
- var actualKey string = k
224
+ var value interface {} = nil
225
+ var skipValue interface {} = nil
220
226
221
- if strings .HasSuffix (k , "<" ) {
227
+ if filter .Equal != nil {
228
+ operator = "="
229
+ value = * filter .Equal
230
+ } else if filter .Less != nil {
222
231
operator = "<"
223
- actualKey = strings . TrimSuffix ( k , "<" )
224
- } else if strings . HasSuffix ( k , ">" ) {
232
+ value = * filter . Less
233
+ } else if filter . Greater != nil {
225
234
operator = ">"
226
- actualKey = strings . TrimSuffix ( k , ">" )
227
- } else if strings . HasSuffix ( k , "^" ) {
235
+ value = * filter . Greater
236
+ } else if filter . Prefix != nil {
228
237
operator = "^"
229
- actualKey = strings .TrimSuffix (k , "^" )
238
+ value = * filter .Prefix
239
+
240
+ // Check for Skip value
241
+ if filter .Skip != nil {
242
+ skipValue = * filter .Skip
243
+ }
244
+ }
245
+
246
+ if value == nil {
247
+ filters = append (filters , filter .Key )
248
+ continue
230
249
}
231
250
232
- switch val := v .(type ) {
251
+ var filterStr string
252
+ switch val := value .(type ) {
233
253
case string :
234
- filters = append ( filters , fmt .Sprintf (`%s%s"%s"` , actualKey , operator , val ) )
254
+ filterStr = fmt .Sprintf (`%s%s"%s"` , filter . Key , operator , val )
235
255
case float64 :
236
- filters = append ( filters , fmt .Sprintf (`%s%s%g` , actualKey , operator , val ) )
256
+ filterStr = fmt .Sprintf (`%s%s%g` , filter . Key , operator , val )
237
257
case bool :
238
- filters = append (filters , fmt .Sprintf (`%s%s%v` , actualKey , operator , val ))
258
+ filterStr = fmt .Sprintf (`%s%s%v` , filter .Key , operator , val )
259
+ default :
260
+ filterStr = fmt .Sprintf (`%s%s%v` , filter .Key , operator , val )
261
+ }
262
+
263
+ // Append skip part if it exists
264
+ if skipValue != nil {
265
+ switch skipVal := skipValue .(type ) {
266
+ case string :
267
+ filterStr += fmt .Sprintf (`$"%s"` , skipVal )
268
+ case float64 :
269
+ filterStr += fmt .Sprintf (`$%g` , skipVal )
270
+ case bool :
271
+ filterStr += fmt .Sprintf (`$%v` , skipVal )
272
+ default :
273
+ filterStr += fmt .Sprintf (`$%v` , skipVal )
274
+ }
239
275
}
276
+
277
+ filters = append (filters , filterStr )
240
278
}
241
279
parts = append (parts , fmt .Sprintf ("(%s)" , strings .Join (filters , " " )))
242
280
}
@@ -306,8 +344,8 @@ func (p *Parser) ParseQuery() (*Query, error) {
306
344
return query , nil
307
345
}
308
346
309
- func (p * Parser ) parseFilter () (map [ string ] interface {} , error ) {
310
- filter := make (map [ string ] interface {} )
347
+ func (p * Parser ) parseFilter () ([]openapi. Filter , error ) {
348
+ filters := make ([]openapi. Filter , 0 )
311
349
312
350
p .nextToken () // consume (
313
351
@@ -326,7 +364,11 @@ func (p *Parser) parseFilter() (map[string]interface{}, error) {
326
364
p .nextToken ()
327
365
328
366
if p .curToken .Type == TOKEN_RPAREN || p .curToken .Type == TOKEN_IDENT {
329
- filter [key ] = nil
367
+ // Create a filter with just a key (no operator/value)
368
+ filter := openapi.Filter {
369
+ Key : key ,
370
+ }
371
+ filters = append (filters , filter )
330
372
continue
331
373
}
332
374
@@ -378,18 +420,84 @@ func (p *Parser) parseFilter() (map[string]interface{}, error) {
378
420
}
379
421
}
380
422
381
- // Store value with appropriate operator metadata
423
+ // Create filter with appropriate operator
424
+ filter := openapi.Filter {
425
+ Key : key ,
426
+ }
427
+
428
+ // Set the operator-specific field
382
429
switch operator {
383
430
case TOKEN_EQUALS :
384
- filter [ key ] = processedValue
431
+ filter . Equal = & processedValue
385
432
case TOKEN_LESS :
386
- filter [ key + "<" ] = processedValue
433
+ filter . Less = & processedValue
387
434
case TOKEN_GREATER :
388
- filter [ key + ">" ] = processedValue
435
+ filter . Greater = & processedValue
389
436
case TOKEN_PREFIX :
390
- filter [key + "^" ] = processedValue
437
+ filter .Prefix = & processedValue
438
+
439
+ // Check for SKIP operation after a PREFIX
440
+ p .nextToken ()
441
+
442
+ if p .curToken .Type == TOKEN_SKIP {
443
+ // We found a skip operation, advance and get the skip value
444
+ p .nextToken ()
445
+
446
+ if p .curToken .Type != TOKEN_IDENT && p .curToken .Type != TOKEN_STRING && p .curToken .Type != TOKEN_PARAM {
447
+ return nil , fmt .Errorf ("expected identifier, string, or parameter placeholder as skip value, got %s" , tokenName (p .curToken .Type ))
448
+ }
449
+
450
+ var skipValue interface {}
451
+
452
+ if p .curToken .Type == TOKEN_PARAM {
453
+ // Handle parameter placeholder for skip
454
+ if p .collectingOnly {
455
+ p .paramIndex ++
456
+ skipValue = nil
457
+ } else {
458
+ if p .paramIndex >= len (p .params ) {
459
+ return nil , fmt .Errorf ("not enough parameters provided for skip, needed at least %d" , p .paramIndex + 1 )
460
+ }
461
+ skipValue = p .params [p .paramIndex ]
462
+ p .paramIndex ++
463
+ }
464
+ } else {
465
+ // Handle literal skip values
466
+ skip := p .curToken .Literal
467
+
468
+ if p .curToken .Type == TOKEN_IDENT {
469
+ if skip == "true" {
470
+ skipValue = true
471
+ } else if skip == "false" {
472
+ skipValue = false
473
+ } else if num , err := strconv .ParseFloat (skip , 64 ); err == nil {
474
+ skipValue = num
475
+ } else {
476
+ skipValue = skip
477
+ }
478
+ } else if p .curToken .Type == TOKEN_STRING {
479
+ skipValue = skip
480
+ }
481
+ }
482
+
483
+ // Set the Skip field in the filter
484
+ filter .Skip = & skipValue
485
+
486
+ // Add the filter with both Prefix and Skip to the filters slice
487
+ filters = append (filters , filter )
488
+
489
+ p .nextToken ()
490
+ continue // Skip the next token advancement since we've already done it
491
+ } else {
492
+ // No skip operation, add the filter with just the prefix
493
+ filters = append (filters , filter )
494
+ continue // Skip the p.nextToken() at the end of the loop since we already advanced
495
+ }
496
+ default :
497
+ // For other operators, proceed normally
391
498
}
392
499
500
+ filters = append (filters , filter )
393
501
p .nextToken ()
394
502
}
395
503
@@ -398,7 +506,7 @@ func (p *Parser) parseFilter() (map[string]interface{}, error) {
398
506
}
399
507
p .nextToken ()
400
508
401
- return filter , nil
509
+ return filters , nil
402
510
}
403
511
404
512
func (p * Parser ) parseNested () ([]* Query , error ) {
0 commit comments