| 431 | } |
| 432 | |
| 433 | func getDatabaseMetadataFilter(filter string) (*metadataFilter, error) { |
| 434 | if filter == "" { |
| 435 | return nil, nil |
| 436 | } |
| 437 | |
| 438 | e, err := cel.NewEnv() |
| 439 | if err != nil { |
| 440 | return nil, connect.NewError(connect.CodeInternal, errors.Errorf("failed to create cel env")) |
| 441 | } |
| 442 | ast, iss := e.Parse(filter) |
| 443 | if iss != nil { |
| 444 | return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("failed to parse filter %v, error: %v", filter, iss.String())) |
| 445 | } |
| 446 | |
| 447 | var getFilter func(expr celast.Expr) error |
| 448 | metaFilter := &metadataFilter{} |
| 449 | |
| 450 | getFilter = func(expr celast.Expr) error { |
| 451 | switch expr.Kind() { |
| 452 | case celast.CallKind: |
| 453 | functionName := expr.AsCall().FunctionName() |
| 454 | switch functionName { |
| 455 | case celoperators.LogicalAnd: |
| 456 | for _, arg := range expr.AsCall().Args() { |
| 457 | if err := getFilter(arg); err != nil { |
| 458 | return err |
| 459 | } |
| 460 | } |
| 461 | return nil |
| 462 | case celoverloads.Contains: |
| 463 | variable := expr.AsCall().Target().AsIdent() |
| 464 | if variable != "table" { |
| 465 | return connect.NewError(connect.CodeInvalidArgument, errors.Errorf("unsupport variable %v", variable)) |
| 466 | } |
| 467 | args := expr.AsCall().Args() |
| 468 | if len(args) != 1 { |
| 469 | return connect.NewError(connect.CodeInvalidArgument, errors.Errorf(`invalid args for %q`, variable)) |
| 470 | } |
| 471 | value := args[0].AsLiteral().Value() |
| 472 | strValue, ok := value.(string) |
| 473 | if !ok { |
| 474 | return connect.NewError(connect.CodeInvalidArgument, errors.Errorf("expect string, got %T, hint: filter literals should be string", value)) |
| 475 | } |
| 476 | metaFilter.table = &tableMetadataFilter{ |
| 477 | name: strings.ToLower(strValue), |
| 478 | wildcard: true, |
| 479 | } |
| 480 | return nil |
| 481 | case celoperators.Equals: |
| 482 | variable, value := getVariableAndValueFromExpr(expr) |
| 483 | strValue, ok := value.(string) |
| 484 | if !ok { |
| 485 | return connect.NewError(connect.CodeInvalidArgument, errors.Errorf("unexpected string but found %q", value)) |
| 486 | } |
| 487 | switch variable { |
| 488 | case "schema": |
| 489 | metaFilter.schema = new(strings.ToLower(strValue)) |
| 490 | case "table": |