@@ -521,6 +521,238 @@ sqlExternalTables:
521521 precision: integer
522522` ` `
523523
524+ # ## Query Parameter Pushdown (`queryParamPushdown`)
525+
526+ Enables SQL clause pushdown to API query parameters. Supports OData and custom API dialects for filter, projection, ordering, and limit operations.
527+
528+ **Location:** Can be set at **provider, providerService, service, resource, or method level**. Config inherits from higher levels, with lower levels overriding higher levels:
529+
530+ ```
531+ Method -> Resource -> Service -> ProviderService -> Provider
532+ ```
533+
534+ This allows you to set a default OData config at the service level and have all resources/methods inherit it, while still allowing specific methods to override with custom settings.
535+
536+ ```yaml
537+ x-stackQL-config:
538+ queryParamPushdown:
539+ # Column projection (SELECT clause pushdown)
540+ select:
541+ dialect: odata | custom # "custom" is default; "odata" applies OData defaults
542+ paramName: "$select" # Not required for OData (default: "$select")
543+ delimiter: "," # Not required for OData (default: ",")
544+ supportedColumns: # Optional, omit or ["*"] for all columns
545+ - "id"
546+ - "name"
547+ - "status"
548+
549+ # Row filtering (WHERE clause pushdown)
550+ filter:
551+ dialect: odata | custom # "custom" is default; "odata" applies OData defaults
552+ paramName: "$filter" # Not required for OData (default: "$filter")
553+ syntax: odata # Not required for OData (default: "odata")
554+ supportedOperators: # Required - which operators can be pushed down
555+ - "eq"
556+ - "ne"
557+ - "gt"
558+ - "lt"
559+ - "ge"
560+ - "le"
561+ - "contains"
562+ - "startswith"
563+ supportedColumns: # Optional, omit or ["*"] for all columns
564+ - "displayName"
565+ - "status"
566+ - "createdDate"
567+
568+ # Ordering (ORDER BY clause pushdown)
569+ orderBy:
570+ dialect: odata | custom # "custom" is default; "odata" applies OData defaults
571+ paramName: "$orderby" # Not required for OData (default: "$orderby")
572+ syntax: odata # Not required for OData (default: "odata")
573+ supportedColumns: # Optional, omit or ["*"] for all columns
574+ - "name"
575+ - "createdDate"
576+
577+ # Row limit (LIMIT clause pushdown)
578+ top:
579+ dialect: odata | custom # "custom" is default; "odata" applies OData defaults
580+ paramName: "$top" # Not required for OData (default: "$top")
581+ maxValue: 1000 # Optional, cap on pushdown value
582+
583+ # Count (SELECT COUNT(*) pushdown)
584+ count:
585+ dialect: odata | custom # "custom" is default; "odata" applies OData defaults
586+ paramName: "$count" # Not required for OData (default: "$count")
587+ paramValue: "true" # Not required for OData (default: "true")
588+ responseKey: "@odata.count"# Not required for OData (default: "@odata.count")
589+ ```
590+
591+ ** Minimal OData Configuration:**
592+
593+ When using OData dialect, defaults are applied automatically:
594+
595+ ``` yaml
596+ x-stackQL-config :
597+ queryParamPushdown :
598+ select : {}
599+ filter :
600+ dialect : odata
601+ supportedOperators : ["eq", "ne", "gt", "lt", "contains"]
602+ orderBy :
603+ dialect : odata
604+ top :
605+ dialect : odata
606+ count :
607+ dialect : odata
608+ ` ` `
609+
610+ **Custom API Configuration:**
611+
612+ For APIs with custom query parameter names:
613+
614+ ` ` ` yaml
615+ x-stackQL-config :
616+ queryParamPushdown :
617+ select :
618+ paramName : " fields"
619+ delimiter : " ,"
620+ filter :
621+ paramName : " filter"
622+ syntax : " key_value" # filter[status]=active&filter[region]=us-east-1
623+ supportedOperators :
624+ - " eq"
625+ supportedColumns :
626+ - " status"
627+ - " region"
628+ orderBy :
629+ paramName : " sort"
630+ syntax : " prefix" # sort=-createdAt (prefix - for desc)
631+ supportedColumns :
632+ - " createdAt"
633+ - " name"
634+ top :
635+ paramName : " limit"
636+ maxValue : 100
637+ count :
638+ paramName : " include_count"
639+ paramValue : " 1"
640+ responseKey : " meta.total"
641+ ` ` `
642+
643+ **Supported Filter Syntaxes:**
644+
645+ | Syntax | Example Output | Use Case |
646+ |--------|---------------|----------|
647+ | ` odata` | `$filter=status eq 'active' and region eq 'us-east-1'` | OData APIs |
648+ | `key_value` | `filter[status]=active&filter[region]=us-east-1` | Rails-style APIs |
649+ | `simple` | `status=active®ion=us-east-1` | Basic query params |
650+
651+ **Supported OrderBy Syntaxes:**
652+
653+ | Syntax | Example | Notes |
654+ |--------|---------|-------|
655+ | `odata` | `$orderby=name desc,date asc` | Space-separated direction |
656+ | `prefix` | `sort=-name,+date` | `-` for desc, `+` or none for asc |
657+ | `suffix` | `sort=name:desc,date:asc` | Colon-separated direction |
658+
659+ **Column/Operator Support Logic:**
660+
661+ | Value | Behavior |
662+ |-------|----------|
663+ | omitted / `null` | All items allowed |
664+ | `["*"]` | Explicit "all items" (same as omitted) |
665+ | `["col1", "col2"]` | Only these items supported |
666+ | `[]` | No items supported (effectively disabled) |
667+
668+ **OData Example with Inheritance (TripPin Reference Service):**
669+
670+ Set a default config at service level, then override at resource or method level as needed :
671+
672+ ` ` ` yaml
673+ # Service-level config - inherited by all resources/methods
674+ x-stackQL-config:
675+ queryParamPushdown:
676+ select:
677+ dialect: odata
678+ filter:
679+ dialect: odata
680+ supportedOperators:
681+ - "eq"
682+ - "ne"
683+ orderBy:
684+ dialect: odata
685+ top:
686+ dialect: odata
687+ count:
688+ dialect: odata
689+
690+ components:
691+ x-stackQL-resources:
692+ # Inherits service-level config (no override needed)
693+ airlines:
694+ id: odata.trippin.airlines
695+ name: airlines
696+ methods:
697+ list:
698+ operation:
699+ $ref: '#/paths/~1Airlines/get'
700+ # No config - inherits from service level
701+ sqlVerbs:
702+ select:
703+ - $ref: '#/components/x-stackQL-resources/airlines/methods/list'
704+
705+ # Resource-level override with full operator support
706+ people:
707+ id: odata.trippin.people
708+ name: people
709+ config:
710+ queryParamPushdown:
711+ filter:
712+ dialect: odata
713+ supportedOperators:
714+ - "eq"
715+ - "ne"
716+ - "gt"
717+ - "lt"
718+ - "contains"
719+ - "startswith"
720+ methods:
721+ list:
722+ operation:
723+ $ref: '#/paths/~1People/get'
724+ sqlVerbs:
725+ select:
726+ - $ref: '#/components/x-stackQL-resources/people/methods/list'
727+
728+ # Method-level override with restricted columns
729+ airports:
730+ id: odata.trippin.airports
731+ name: airports
732+ methods:
733+ list:
734+ operation:
735+ $ref: '#/paths/~1Airports/get'
736+ config:
737+ queryParamPushdown:
738+ select:
739+ dialect: odata
740+ supportedColumns:
741+ - "Name"
742+ - "IcaoCode"
743+ filter:
744+ dialect: odata
745+ supportedColumns:
746+ - "Name"
747+ - "IcaoCode"
748+ top:
749+ dialect: odata
750+ maxValue: 100
751+ sqlVerbs:
752+ select:
753+ - $ref: '#/components/x-stackQL-resources/airports/methods/list'
754+ ` ` `
755+
524756---
525757
526758# # Method Definition
0 commit comments