diff --git a/.github/actions/start-envio-serve/action.yml b/.github/actions/start-envio-serve/action.yml new file mode 100644 index 0000000000..9cabd63222 --- /dev/null +++ b/.github/actions/start-envio-serve/action.yml @@ -0,0 +1,67 @@ +name: Start envio serve +description: > + Start `envio serve` in the background and poll /healthz until it + responds (60 x 1s), failing the step if it never comes up. Set + `restart: "true"` to first kill a previously started serve process + (e.g. to bring it back up with different Hasura-compat env vars). + +inputs: + working-directory: + description: Directory to run `envio serve` from. + required: false + default: scenarios/test_codegen + port: + description: Port to serve on. + required: false + default: "8081" + hasura-response-limit: + description: Value for ENVIO_HASURA_RESPONSE_LIMIT (empty to unset the limit). + required: false + default: "" + hasura-public-aggregate: + description: Value for ENVIO_HASURA_PUBLIC_AGGREGATE (empty to disable aggregates). + required: false + default: "" + restart: + description: > + Kill a previously started `bin.mjs serve` process before starting + this one. + required: false + default: "false" + +runs: + using: composite + steps: + - name: Start envio serve + shell: bash + working-directory: ${{ inputs.working-directory }} + env: + ENVIO_SERVE_PORT_INPUT: ${{ inputs.port }} + ENVIO_HASURA_RESPONSE_LIMIT: ${{ inputs.hasura-response-limit }} + ENVIO_HASURA_PUBLIC_AGGREGATE: ${{ inputs.hasura-public-aggregate }} + RESTART_INPUT: ${{ inputs.restart }} + run: | + if [ "$RESTART_INPUT" = "true" ]; then + pkill -f "bin.mjs serve" || true + # Wait until the old process is actually gone and the port is + # free before starting the replacement — a fixed sleep races the + # OS releasing the listener. + for i in {1..30}; do + if ! pgrep -f "bin.mjs serve" >/dev/null \ + && ! curl -sf --max-time 1 "http://localhost:$ENVIO_SERVE_PORT_INPUT/healthz" >/dev/null 2>&1; then + break + fi + if [ "$i" = "30" ]; then + echo "old envio serve did not exit; force-killing" + pkill -9 -f "bin.mjs serve" || true + sleep 1 + fi + sleep 1 + done + fi + pnpm exec envio serve --port "$ENVIO_SERVE_PORT_INPUT" & + for i in {1..60}; do + if curl -sSf "http://localhost:$ENVIO_SERVE_PORT_INPUT/healthz" >/dev/null; then echo "envio serve is up"; exit 0; fi + sleep 1 + done + echo "envio serve did not become ready"; exit 1 diff --git a/.github/workflows/build_and_verify.yml b/.github/workflows/build_and_verify.yml index e1065f52ec..4c0e0d7d87 100644 --- a/.github/workflows/build_and_verify.yml +++ b/.github/workflows/build_and_verify.yml @@ -15,7 +15,6 @@ permissions: env: CARGO_TERM_COLOR: always - ENVIO_API_TOKEN: ${{ secrets.ENVIO_API_TOKEN }} FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: @@ -136,6 +135,11 @@ jobs: run: cargo clippy -- -D warnings - name: Cargo Test + env: + # Docker-gated tests (serve robustness/TLS) skip silently when + # docker is missing; on CI runners that would be a vacuous pass, + # so require docker and fail loudly instead. + ENVIO_REQUIRE_DOCKER: "1" run: cargo test --no-default-features # Hypersync endpoint health check - non-blocking, external dependency @@ -163,6 +167,8 @@ jobs: runs-on: ubuntu-latest needs: build-envio-package timeout-minutes: 9 + env: + ENVIO_API_TOKEN: ${{ secrets.ENVIO_API_TOKEN }} steps: - uses: actions/checkout@v6 @@ -180,9 +186,14 @@ jobs: runs-on: ubuntu-latest needs: build-envio-package timeout-minutes: 9 + env: + ENVIO_API_TOKEN: ${{ secrets.ENVIO_API_TOKEN }} + # postgres/hasura anchors defined here (first job needing them, in file + # order) and reused via aliases below to avoid repeating the identical + # `services:` blocks in every job that needs the same containers. services: - postgres: + postgres: &postgres-service image: postgres:16 env: POSTGRES_PASSWORD: testing @@ -196,7 +207,7 @@ jobs: ports: - 5433:5432 - hasura: + hasura: &hasura-service image: hasura/graphql-engine:v2.43.0 env: HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:testing@postgres:5432/envio-dev @@ -256,40 +267,169 @@ jobs: details: "Tests Failed on main!" webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} + # Differential GraphQL test - envio serve must match real Hasura + # response-for-response on the recorded corpus. This is the REQUIRED, + # fast path: it diffs against the committed oracle snapshots + # (fixtures/differential/snapshots/) instead of a live Hasura instance, + # so it needs Postgres only. Hasura is used just to *populate* those + # snapshots (`pnpm record:differential`, run locally/manually whenever + # the corpus changes, not on every CI run) - see + # differential-test-live below for the live-Hasura confidence check. + differential-test: + runs-on: ubuntu-latest + needs: build-envio-package + timeout-minutes: 9 + + services: + postgres: *postgres-service + + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + - uses: ./.github/actions/prepare-envio-artifacts + + - name: Ensure psql is available + run: which psql || (sudo apt-get update && sudo apt-get install -y --no-install-recommends postgresql-client) + + - name: Apply fixture schema + seed + run: | + PGPASSWORD=testing psql -h localhost -p 5433 -U postgres -d envio-dev -v ON_ERROR_STOP=1 \ + -f packages/e2e-tests/fixtures/differential/schema.sql \ + -f packages/e2e-tests/fixtures/differential/seed.sql + + - name: Start envio serve (default phase) + uses: ./.github/actions/start-envio-serve + + - name: Diff default phase against oracle snapshots + working-directory: packages/e2e-tests + run: pnpm exec tsx src/differential/diffServe.ts + + - name: Restart envio serve (limited phase) + uses: ./.github/actions/start-envio-serve + with: + restart: "true" + hasura-response-limit: "5" + hasura-public-aggregate: '["User","Token","SimpleEntity","raw_events","_meta"]' + + - name: Diff limited phase against oracle snapshots + working-directory: packages/e2e-tests + run: pnpm exec tsx src/differential/diffServe.ts --phase limited + + # Live-Hasura PR validation. Reuse one Postgres + Hasura environment to + # verify the committed snapshots, run the full HTTP + WebSocket suite, + # and exercise envio serve under a short bounded load. Snapshot drift is + # required; the slower live-parity and soak checks remain informational. + differential-test-live: + runs-on: ubuntu-latest + needs: build-envio-package + timeout-minutes: 20 + + services: + postgres: *postgres-service + hasura: *hasura-service + + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + - uses: ./.github/actions/prepare-envio-artifacts + + - name: Wait for Hasura + run: | + for i in {1..60}; do + if curl -sSf http://localhost:8080/healthz >/dev/null; then + echo "Hasura is up"; exit 0; fi; sleep 1; done + echo "Hasura did not become ready"; exit 1 + + - name: Re-record snapshots against live Hasura + working-directory: packages/e2e-tests + run: pnpm record:differential + + - name: Fail on snapshot drift + run: | + git add -N packages/e2e-tests/fixtures/differential/snapshots + git diff --exit-code -- packages/e2e-tests/fixtures/differential/snapshots + + - name: Run live differential suite (HTTP + WebSocket) + continue-on-error: true + working-directory: packages/e2e-tests + run: pnpm test:differential + + - name: Start envio serve + continue-on-error: true + uses: ./.github/actions/start-envio-serve + + # 60s bounded soak smoke: server stays up, no 5xx, no fd/RSS blowup. + # p99-drift comparison is meaningless over windows this short on + # shared runners, so its threshold is effectively disabled. + - name: Soak smoke (60s) + continue-on-error: true + working-directory: packages/e2e-tests + run: | + pnpm exec tsx src/differential/soakLoad.ts \ + --duration 60s --concurrency 16 --p99-drift-multiplier 1000 + + # Performance + resource benchmark: envio serve vs a Hasura baseline + # recorded fresh on the SAME runner in the SAME job (CI hardware varies + # run to run, so the locally-committed hasura-baseline.json isn't a fair + # same-machine comparison here). Informational only - never blocks a + # merge on a regression, since CI runners have enough performance + # variance on their own that a hard threshold would be flaky. + differential-benchmark: + runs-on: ubuntu-latest + needs: build-envio-package + timeout-minutes: 15 + continue-on-error: true + + services: + postgres: *postgres-service + hasura: *hasura-service + + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + - uses: ./.github/actions/prepare-envio-artifacts + + - name: Wait for Hasura + run: | + for i in {1..60}; do + if curl -sSf http://localhost:8080/healthz >/dev/null; then + echo "Hasura is up"; exit 0; fi; sleep 1; done + echo "Hasura did not become ready"; exit 1 + + - name: Seed bench dataset + record Hasura baseline + working-directory: packages/e2e-tests + run: | + pnpm exec tsx src/differential/setupBenchDataset.ts + pnpm exec tsx src/differential/bench.ts --record-baseline --all --budget-ms 800 --min-iters 2 --max-iters 15 + + - name: Start envio serve + uses: ./.github/actions/start-envio-serve + + - name: Benchmark envio serve against the fresh baseline + working-directory: packages/e2e-tests + run: pnpm exec tsx src/differential/bench.ts --all --budget-ms 800 --min-iters 2 --max-iters 15 + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: bench-report + path: packages/e2e-tests/bench-report.md + retention-days: 30 + # E2E test - runs envio dev with a real indexer scenario e2e-test: runs-on: ubuntu-latest needs: build-envio-package timeout-minutes: 9 + env: + ENVIO_API_TOKEN: ${{ secrets.ENVIO_API_TOKEN }} services: - postgres: - image: postgres:16 - env: - POSTGRES_PASSWORD: testing - POSTGRES_DB: envio-dev - POSTGRES_USER: postgres - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5433:5432 - - hasura: - image: hasura/graphql-engine:v2.43.0 - env: - HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:testing@postgres:5432/envio-dev - HASURA_GRAPHQL_ENABLE_CONSOLE: "true" - HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log - HASURA_GRAPHQL_NO_OF_RETRIES: 10 - HASURA_GRAPHQL_ADMIN_SECRET: testing - HASURA_GRAPHQL_STRINGIFY_NUMERIC_TYPES: "true" - HASURA_GRAPHQL_UNAUTHORIZED_ROLE: public - PORT: 8080 - ports: - - 8080:8080 + postgres: *postgres-service + hasura: *hasura-service clickhouse: image: clickhouse/clickhouse-server:26.2.15.4 diff --git a/.gitignore b/.gitignore index 608bafff66..fb5ae11fc7 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ target .pnpm-store node_modules +# Claude Code agent worktrees (local scratch space, never repo content) +.claude/worktrees/ + #All generated code for scenarios scenarios/**/generated scenarios/**/*.bs.js diff --git a/Cargo.lock b/Cargo.lock index 02a45fe711..e5b85eabca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -915,6 +915,61 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "axum" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +dependencies = [ + "axum-core", + "base64 0.22.1", + "bytes", + "form_urlencoded", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sha1", + "sync_wrapper 1.0.2", + "tokio", + "tokio-tungstenite", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper 1.0.2", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "base16ct" version = "0.2.0" @@ -996,6 +1051,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bollard" version = "0.20.1" @@ -1180,6 +1244,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + [[package]] name = "chrono" version = "0.4.44" @@ -1240,6 +1315,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "colorchoice" version = "1.0.4" @@ -1285,7 +1366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af9a108e542ddf1de36743a6126e94d6659dccda38fc8a77e80b915102ac784a" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "proptest", "serde_core", ] @@ -1296,6 +1377,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "const-random" version = "0.1.18" @@ -1398,6 +1485,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -1485,6 +1581,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "csv" version = "1.4.0" @@ -1522,6 +1627,15 @@ version = "0.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7ab264ea985f1bd27887d7b21ea2bb046728e05d11909ca138d700c494730db" +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "darling" version = "0.20.11" @@ -1557,16 +1671,70 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + +[[package]] +name = "deadpool" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" +dependencies = [ + "deadpool-runtime", + "lazy_static", + "num_cpus", + "tokio", +] + +[[package]] +name = "deadpool-postgres" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d697d376cbfa018c23eb4caab1fd1883dd9c906a8c034e8d9a3cb06a7e0bef9" +dependencies = [ + "async-trait", + "deadpool", + "getrandom 0.2.17", + "tokio", + "tokio-postgres", + "tracing", +] + +[[package]] +name = "deadpool-runtime" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" +dependencies = [ + "tokio", +] + [[package]] name = "der" version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid", + "const-oid 0.9.6", + "der_derive", + "flagset", "zeroize", ] +[[package]] +name = "der_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1675,12 +1843,24 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", + "block-buffer 0.10.4", + "const-oid 0.9.6", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "const-oid 0.10.2", + "crypto-common 0.2.2", + "ctutils", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1844,11 +2024,13 @@ dependencies = [ "anyhow", "arrayvec", "async-recursion", + "axum", "bollard", "clap", "clap-markdown", "colored", "convert_case 0.6.0", + "deadpool-postgres", "env_logger", "faster-hex", "fuel-abi-types", @@ -1863,6 +2045,7 @@ dependencies = [ "inquire", "insta", "itertools 0.11.0", + "lru", "napi", "napi-build", "napi-derive", @@ -1875,18 +2058,27 @@ dependencies = [ "regex", "reqwest 0.11.27", "ruint", + "rustls", + "rustls-native-certs", + "rustls-pemfile", "schemars", "serde", "serde_json", "serde_yaml", - "sha2", + "sha2 0.10.9", + "socket2 0.5.10", "strum 0.26.3", "strum_macros 0.26.4", "subenum", + "subtle", "tar", "tempdir", "thiserror 1.0.69", "tokio", + "tokio-postgres", + "tokio-postgres-rustls", + "tokio-tungstenite", + "tracing", "tracing-subscriber", ] @@ -1923,6 +2115,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "fallible-streaming-iterator" version = "0.1.9" @@ -2016,6 +2214,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "flagset" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" + [[package]] name = "flatbuffers" version = "25.12.19" @@ -2222,7 +2426,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -2249,6 +2453,7 @@ dependencies = [ "cfg-if", "libc", "r-efi", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -2358,6 +2563,8 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ + "allocator-api2", + "equivalent", "foldhash 0.1.5", "serde", ] @@ -2400,6 +2607,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest 0.11.3", +] + [[package]] name = "http" version = "0.2.12" @@ -2467,6 +2683,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "0.14.32" @@ -2723,7 +2948,7 @@ dependencies = [ "reqwest 0.12.28", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "thiserror 1.0.69", "tokio", "tracing", @@ -3135,7 +3360,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -3144,7 +3369,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -3248,6 +3473,15 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -3275,6 +3509,15 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.5", +] + [[package]] name = "lru-slab" version = "0.1.2" @@ -3320,6 +3563,31 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "md-5" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +dependencies = [ + "cfg-if", + "digest 0.11.3", +] + [[package]] name = "memchr" version = "2.8.0" @@ -3365,7 +3633,7 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -3376,7 +3644,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] @@ -3576,6 +3844,24 @@ dependencies = [ "libc", ] +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "objc2-system-configuration" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" +dependencies = [ + "objc2-core-foundation", +] + [[package]] name = "object" version = "0.37.3" @@ -3826,7 +4112,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ "pest", - "sha2", + "sha2 0.10.9", +] + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_shared", + "serde", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", ] [[package]] @@ -3999,6 +4304,35 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "postgres-protocol" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08808e3c483c46e999108051c78334f473d5adb59d78bb80a1268c7e6aa6c514" +dependencies = [ + "base64 0.22.1", + "byteorder", + "bytes", + "fallible-iterator", + "hmac 0.13.0", + "md-5", + "memchr", + "rand 0.10.1", + "sha2 0.11.0", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "851ca9db4932932d69f3ea811b1abe63087a0f740a47692619dd40d4899b68be" +dependencies = [ + "bytes", + "fallible-iterator", + "postgres-protocol", +] + [[package]] name = "potential_utf" version = "0.1.4" @@ -4235,6 +4569,17 @@ dependencies = [ "serde", ] +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.1", + "rand_core 0.10.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -4289,6 +4634,12 @@ dependencies = [ "serde", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_xorshift" version = "0.4.0" @@ -4517,7 +4868,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac", + "hmac 0.12.1", "subtle", ] @@ -4708,7 +5059,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5525db49c7719816ac719ea8ffd0d0b4586db1a3f5d3e7751593230dacc642fd" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", "fastrange-rs", ] @@ -4883,6 +5234,17 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + [[package]] name = "serde_repr" version = "0.1.20" @@ -4919,6 +5281,17 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.10.9" @@ -4926,10 +5299,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", +] + [[package]] name = "sha3" version = "0.10.8" @@ -5024,6 +5408,12 @@ version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + [[package]] name = "slab" version = "0.4.12" @@ -5129,6 +5519,17 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "strsim" version = "0.11.1" @@ -5426,6 +5827,27 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tls_codec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "tokio" version = "1.49.0" @@ -5463,6 +5885,47 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-postgres" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a528f7d280f6d5b9cd149635c8705b0dd049754bc67d81d31fa25169a93809d3" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator", + "futures-channel", + "futures-util", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "rand 0.10.1", + "socket2 0.6.2", + "tokio", + "tokio-util", + "whoami", +] + +[[package]] +name = "tokio-postgres-rustls" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2ad44aa0ae96db89c4742212ed41645b2f597311ff6e1945542a4d9fadc2fb" +dependencies = [ + "rustls", + "rustls-native-certs", + "sha2 0.11.0", + "tokio", + "tokio-postgres", + "tokio-rustls", + "x509-cert", +] + [[package]] name = "tokio-rustls" version = "0.26.4" @@ -5473,6 +5936,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.18" @@ -5530,6 +6005,7 @@ dependencies = [ "tokio", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -5568,6 +6044,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5611,10 +6088,14 @@ version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] @@ -5625,6 +6106,22 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8" +dependencies = [ + "bytes", + "data-encoding", + "http 1.4.0", + "httparse", + "log", + "rand 0.9.2", + "sha1", + "thiserror 2.0.18", +] + [[package]] name = "twox-hash" version = "2.1.2" @@ -5661,12 +6158,33 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -5775,6 +6293,15 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + [[package]] name = "wasip2" version = "1.0.2+wasi-0.2.9" @@ -5793,6 +6320,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasite" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fe902b4a6b8028a753d5424909b764ccf79b7a209eac9bf97e59cda9f71a42" +dependencies = [ + "wasi 0.14.7+wasi-0.2.4", +] + [[package]] name = "wasm-bindgen" version = "0.2.113" @@ -5928,6 +6464,19 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "whoami" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6a5b12f9df4f978d2cfdb1bd3bac52433f44393342d7ee9c25f5a1c14c0f45d" +dependencies = [ + "libc", + "libredox", + "objc2-system-configuration", + "wasite", + "web-sys", +] + [[package]] name = "winapi" version = "0.3.9" @@ -6362,6 +6911,18 @@ dependencies = [ "tap", ] +[[package]] +name = "x509-cert" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" +dependencies = [ + "const-oid 0.9.6", + "der", + "spki", + "tls_codec", +] + [[package]] name = "xattr" version = "1.6.1" diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index fb7377ff80..417099d324 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -34,6 +34,7 @@ tokio = { version = "1.49", features = [ "time", "fs", "io-util", + "signal", ] } anyhow = "1.0.101" sha2 = "0.10.8" @@ -60,6 +61,20 @@ futures-util = "0.3" tar = "0.4" napi = { version = "=3.8.5", features = ["napi10", "async", "serde-json"] } napi-derive = "=3.5.4" +axum = { version = "0.8", features = ["ws"] } +socket2 = "0.5" +tokio-postgres = "0.7" +deadpool-postgres = "0.14" +rustls = { version = "0.23", default-features = false, features = ["ring"] } +rustls-native-certs = "0.8" +lru = "0.12" +tracing = "0.1" +tracing-subscriber = { version = "0.3.22", features = ["env-filter"] } +subtle = "2.6" +tokio-postgres-rustls = { version = "0.14", default-features = false, features = [ + "native-certs", + "ring", +] } [features] hypersync_health = [] @@ -77,6 +92,8 @@ paste = "1.0.15" tracing-subscriber = "0.3.22" pretty_assertions = "1.4.1" insta = "1.46" +rustls-pemfile = "1.0" +tokio-tungstenite = "0.29" # NOTE: this is needed for aarch64 linux, since linking of openssl has caused issues via the package manager # See here for this workaround: https://docs.rs/openssl/latest/openssl/#vendored diff --git a/packages/cli/CommandLineHelp.md b/packages/cli/CommandLineHelp.md index 990b93da8b..891f9be934 100644 --- a/packages/cli/CommandLineHelp.md +++ b/packages/cli/CommandLineHelp.md @@ -30,6 +30,7 @@ This document contains the help content for the `envio` command-line program. * [`envio start`↴](#envio-start) * [`envio metrics`↴](#envio-metrics) * [`envio metrics runtime`↴](#envio-metrics-runtime) +* [`envio serve`↴](#envio-serve) * [`envio skills`↴](#envio-skills) * [`envio skills update`↴](#envio-skills-update) * [`envio tools`↴](#envio-tools) @@ -51,6 +52,7 @@ This document contains the help content for the `envio` command-line program. * `local` — Prepare local environment for envio testing * `start` — Start the indexer. Runs codegen automatically before launching so the on-disk types stay in sync with `config.yaml` and `schema.graphql` * `metrics` — Fetch raw Prometheus metrics from the running indexer's /metrics endpoint +* `serve` — Serve the indexed data over a Hasura-compatible GraphQL API * `skills` — Manage Envio-provided Claude Code skills under `.claude/skills/` * `tools` — Tools for people and AI agents (search-docs, fetch-docs). Run `envio tools help` for details * `config` — Inspect the indexer config @@ -401,6 +403,23 @@ Fetch runtime metrics from the running indexer's /metrics/runtime endpoint +## `envio serve` + +Serve the indexed data over a Hasura-compatible GraphQL API + +**Usage:** `envio serve [OPTIONS]` + +###### **Options:** + +* `-p`, `--port ` — The port to serve the GraphQL API on. Can also be set via the `ENVIO_SERVE_PORT` environment variable + + Default value: `8080` +* `--host ` — The host to bind to + + Default value: `0.0.0.0` + + + ## `envio skills` Manage Envio-provided Claude Code skills under `.claude/skills/` diff --git a/packages/cli/src/cli_args/clap_definitions.rs b/packages/cli/src/cli_args/clap_definitions.rs index f66a872f63..f50072b797 100644 --- a/packages/cli/src/cli_args/clap_definitions.rs +++ b/packages/cli/src/cli_args/clap_definitions.rs @@ -62,6 +62,9 @@ pub enum CommandType { ///Fetch raw Prometheus metrics from the running indexer's /metrics endpoint Metrics(MetricsArgs), + ///Serve the indexed data over a Hasura-compatible GraphQL API + Serve(ServeArgs), + ///Manage Envio-provided Claude Code skills under `.claude/skills/` #[command(subcommand)] Skills(SkillsSubcommand), @@ -151,6 +154,17 @@ pub struct MetricsArgs { pub subcommand: Option, } +#[derive(Debug, Args)] +pub struct ServeArgs { + ///The port to serve the GraphQL API on. Can also be set via the `ENVIO_SERVE_PORT` environment variable. + #[arg(short, long, env = "ENVIO_SERVE_PORT", default_value_t = 8080)] + pub port: u16, + + ///The host to bind to + #[arg(long, default_value = "0.0.0.0")] + pub host: String, +} + #[derive(Debug, Subcommand)] pub enum MetricsSubcommand { ///Fetch runtime metrics from the running indexer's /metrics/runtime endpoint diff --git a/packages/cli/src/cli_args/snapshots/envio__cli_args__clap_definitions__test__envio_help_snapshot.snap b/packages/cli/src/cli_args/snapshots/envio__cli_args__clap_definitions__test__envio_help_snapshot.snap index 7d76776d45..496251cbea 100644 --- a/packages/cli/src/cli_args/snapshots/envio__cli_args__clap_definitions__test__envio_help_snapshot.snap +++ b/packages/cli/src/cli_args/snapshots/envio__cli_args__clap_definitions__test__envio_help_snapshot.snap @@ -1,5 +1,6 @@ --- source: packages/cli/src/cli_args/clap_definitions.rs +assertion_line: 517 expression: rendered --- Usage: envio [OPTIONS] @@ -12,6 +13,7 @@ Commands: local Prepare local environment for envio testing start Start the indexer. Runs codegen automatically before launching so the on-disk types stay in sync with `config.yaml` and `schema.graphql` metrics Fetch raw Prometheus metrics from the running indexer's /metrics endpoint + serve Serve the indexed data over a Hasura-compatible GraphQL API skills Manage Envio-provided Claude Code skills under `.claude/skills/` tools Tools for people and AI agents (search-docs, fetch-docs). Run `envio tools help` for details config Inspect the indexer config diff --git a/packages/cli/src/config_parsing/chain_helpers.rs b/packages/cli/src/config_parsing/chain_helpers.rs index 2d00f5ca4f..27ce5d2418 100644 --- a/packages/cli/src/config_parsing/chain_helpers.rs +++ b/packages/cli/src/config_parsing/chain_helpers.rs @@ -342,6 +342,9 @@ pub enum Network { #[subenum(GraphNetwork)] Rinkeby = 4, + #[subenum(HypersyncChain)] + Robinhood = 4663, + #[subenum(HypersyncChain, NetworkWithExplorer)] Rsk = 30, @@ -545,6 +548,7 @@ impl Network { | Network::Plasma | Network::Plume | Network::Rinkeby + | Network::Robinhood | Network::Rsk | Network::Scroll | Network::ScrollSepolia diff --git a/packages/cli/src/config_parsing/entity_parsing.rs b/packages/cli/src/config_parsing/entity_parsing.rs index 1d3a36b273..840c0a7c51 100644 --- a/packages/cli/src/config_parsing/entity_parsing.rs +++ b/packages/cli/src/config_parsing/entity_parsing.rs @@ -110,7 +110,7 @@ impl Schema { let schema_string = std::fs::read_to_string(&schema_path).context(format!( "Failed to read schema file at {}. Please ensure that the schema file is \ placed correctly in the directory.", - &schema_path.to_str().unwrap_or("bad file path"), + schema_path.to_str().unwrap_or("bad file path"), ))?; Self::from_string(&schema_string) @@ -811,7 +811,7 @@ impl Field { } let precision = get_positive_integer(arg_value).context(format!( "Parsing precision.digits directive on BigInt field with field name {}", - &field.name + field.name ))?; pg_type_modifications.big_int_precision = Some(precision); } @@ -828,14 +828,14 @@ impl Field { Some(get_positive_integer(arg_value).context(format!( "Parsing numeric.precision directive on BigDecimal with \ field name {}", - &field.name + field.name ))?); } "scale" => { scale = Some(get_positive_integer(arg_value).context(format!( "Parsing numeric.scale directive on BigDecimal with field \ name {}", - &field.name + field.name ))?); } unknown_param => { diff --git a/packages/cli/src/config_parsing/system_config.rs b/packages/cli/src/config_parsing/system_config.rs index 4d1f7c3525..a301f14ae4 100644 --- a/packages/cli/src/config_parsing/system_config.rs +++ b/packages/cli/src/config_parsing/system_config.rs @@ -1092,7 +1092,7 @@ impl SystemConfig { "Failed to resolve config path {0} (--config {1} resolved relative to \ --directory {2}). Make sure the file exists. Note that --config and \ ENVIO_CONFIG are interpreted relative to --directory.", - &project_paths.config.to_str().unwrap_or("{unknown}"), + project_paths.config.to_str().unwrap_or("{unknown}"), project_paths.config_relative_to_root().display(), project_paths.project_root.display(), ))?; diff --git a/packages/cli/src/config_parsing/validation.rs b/packages/cli/src/config_parsing/validation.rs index a37ac307fb..e9868a4aa9 100644 --- a/packages/cli/src/config_parsing/validation.rs +++ b/packages/cli/src/config_parsing/validation.rs @@ -136,7 +136,7 @@ impl human_config::evm::Chain { return Err(anyhow!( "The config file has an endBlock that is less than the startBlock for \ network id: {}. The endBlock must be greater than the startBlock.", - &self.id.to_string() + self.id )); } } diff --git a/packages/cli/src/executor/init.rs b/packages/cli/src/executor/init.rs index 1097b7ea8c..ac0b3fa146 100644 --- a/packages/cli/src/executor/init.rs +++ b/packages/cli/src/executor/init.rs @@ -76,7 +76,7 @@ pub async fn run_init_args( ) .context(format!( "Failed initializing Fuel template {} at path {:?}", - &template, &parsed_project_paths.project_root, + template, parsed_project_paths.project_root, ))?; } Ecosystem::Svm { @@ -90,7 +90,7 @@ pub async fn run_init_args( ) .context(format!( "Failed initializing Svm template {} at path {:?}", - &template, &parsed_project_paths.project_root, + template, parsed_project_paths.project_root, ))?; } Ecosystem::Evm { @@ -104,7 +104,7 @@ pub async fn run_init_args( ) .context(format!( "Failed initializing Evm template {} at path {:?}", - &template, &parsed_project_paths.project_root, + template, parsed_project_paths.project_root, ))?; } Ecosystem::Fuel { @@ -169,7 +169,7 @@ pub async fn run_init_args( .context(format!( "Failed initializing blank template for Contract Import with language {} at \ path {:?}", - &init_config.language, &parsed_project_paths.project_root, + init_config.language, parsed_project_paths.project_root, ))?; auto_schema_handler_template @@ -233,7 +233,7 @@ pub async fn run_init_args( .context(format!( "Failed initializing blank template for Contract Import with language {} at \ path {:?}", - &init_config.language, &parsed_project_paths.project_root, + init_config.language, parsed_project_paths.project_root, ))?; auto_schema_handler_template diff --git a/packages/cli/src/executor/mod.rs b/packages/cli/src/executor/mod.rs index e075d8c5da..37dce5a7fc 100644 --- a/packages/cli/src/executor/mod.rs +++ b/packages/cli/src/executor/mod.rs @@ -88,6 +88,11 @@ pub async fn execute( Ok(None) } + CommandType::Serve(serve_args) => { + crate::serve::run(&serve_args, &parsed_project_paths).await?; + Ok(None) + } + CommandType::Skills(SkillsSubcommand::Update) => { skills::run_update(&parsed_project_paths)?; Ok(None) diff --git a/packages/cli/src/hbs_templating/hbs_dir_generator.rs b/packages/cli/src/hbs_templating/hbs_dir_generator.rs index 7fa59fadbf..e2fd4bfa67 100644 --- a/packages/cli/src/hbs_templating/hbs_dir_generator.rs +++ b/packages/cli/src/hbs_templating/hbs_dir_generator.rs @@ -88,17 +88,17 @@ impl<'a, T: Serialize> HandleBarsDirGenerator<'a, T> { })?; //ensure the dir exists or is created - fs::create_dir_all(&output_dir_path).context(format!( - "create_dir_all failed at {}", - &output_dir_path_str, - ))?; + fs::create_dir_all(&output_dir_path) + .context( + format!("create_dir_all failed at {}", output_dir_path_str,), + )?; //append the filename let output_file_path = output_dir_path.join(file_stem); //Write the file fs::write(&output_file_path, rendered_file) - .context(format!("file write failed at {}", &output_dir_path_str))?; + .context(format!("file write failed at {}", output_dir_path_str))?; } } DirEntry::Dir(dir) => Self::generate_hbs_templates_internal_recursive( diff --git a/packages/cli/src/lib.rs b/packages/cli/src/lib.rs index ff1c157435..43d412a4af 100644 --- a/packages/cli/src/lib.rs +++ b/packages/cli/src/lib.rs @@ -16,6 +16,7 @@ mod hbs_templating; mod napi; mod project_paths; pub mod scripts; +pub mod serve; mod service_health; mod svm_hypersync_source; mod template_dirs; diff --git a/packages/cli/src/napi.rs b/packages/cli/src/napi.rs index 8d081544f5..681ee1ff69 100644 --- a/packages/cli/src/napi.rs +++ b/packages/cli/src/napi.rs @@ -26,9 +26,18 @@ pub fn get_config_json( .map_err(|e| napi::Error::from_reason(format!("Failed serializing config: {e}"))) } +/// Requests graceful shutdown of a Rust-owned long-running command. Node +/// installs the process signal handlers because libuv owns SIGINT/SIGTERM in +/// the CLI host; Tokio's OS signal future alone is not notified reliably when +/// it runs inside the NAPI async runtime. +#[napi_derive::napi] +pub fn request_shutdown() { + crate::serve::request_shutdown(); +} + /// Returns a JSON-encoded `Command` for JS to dispatch, or `None` when /// Rust has handled the command end-to-end (help/version, codegen, init, -/// stop, docker up/down). The Node process then exits with code 0. +/// serve, stop, docker up/down). The Node process then exits with code 0. #[napi_derive::napi] pub async fn run_cli( args: Vec, diff --git a/packages/cli/src/serve/env_config.rs b/packages/cli/src/serve/env_config.rs new file mode 100644 index 0000000000..00ff55e9bd --- /dev/null +++ b/packages/cli/src/serve/env_config.rs @@ -0,0 +1,977 @@ +//! Environment configuration for `envio serve`, mirroring the exact +//! semantics of packages/envio/src/Env.res: process env wins over the +//! project-root `.env` file, `devFallback` defaults apply only when +//! NODE_ENV != "production", plain fallbacks always apply. +//! +//! TLS (`ENVIO_PG_SSL_MODE`) follows libpq's sslmode values: +//! - `disable` (or `false`, or unset): plaintext, no TLS. +//! - `allow`/`prefer`: TLS if the server supports it, falling back to +//! plaintext otherwise; the server certificate is NOT verified. +//! - `require`: TLS mandatory, but the server certificate is NOT verified +//! (libpq's semantic — works with self-signed certificates). +//! - `verify-ca`/`verify-full` (or `true`, or any other value, for backward +//! compatibility): TLS mandatory and the server certificate is verified +//! against the platform's trusted root CA store. Note `verify-ca` is +//! served as `verify-full` (chain AND hostname verification): rustls's +//! verifier doesn't offer chain-only verification, so `verify-ca` is +//! strictly stricter here than libpq's. + +use crate::project_paths::ParsedProjectPaths; +use crate::utils::dotenv::{self, EnvMap}; +use anyhow::{anyhow, Context}; +use std::time::Duration; + +pub struct ServeEnv { + pub pg_host: String, + pub pg_port: u16, + pub pg_user: String, + pub pg_password: String, + pub pg_database: String, + pub pg_schema: String, + pub pg_ssl: PgSslMode, + pub admin_secret: String, + pub response_limit: Option, + pub aggregate_entities: Vec, + /// ENVIO_SERVE_QUERY_TIMEOUT_MS. Bounds every query both server-side + /// (statement_timeout) and client-side (tokio timeout with slack, so a + /// frozen/unreachable Postgres can't hang requests forever). 0 disables. + pub query_timeout_ms: Option, + /// ENVIO_SERVE_POOL_WAIT_TIMEOUT_MS. Bounds how long a request waits for + /// a free pooled connection before erroring instead of queuing without + /// limit. 0 disables. + pub pool_wait_timeout_ms: Option, + /// ENVIO_SERVE_CONNECT_TIMEOUT_MS. Bounds TCP connect + handshake when + /// the pool opens a new connection. 0 disables. + pub connect_timeout_ms: Option, + /// ENVIO_SERVE_POOL_MAX_SIZE. Defaults to min(cpu_count * 2, 10). + pub pool_max_size: usize, + /// ENVIO_SERVE_STARTUP_RETRY_BUDGET_MS. Total wall-clock budget for + /// retrying pool creation/introspection with exponential backoff when + /// Postgres isn't reachable yet at boot. 0 disables retries. + pub startup_retry_budget_ms: u64, + /// ENVIO_SERVE_HEALTHZ_TIMEOUT_MS. Bounds the /healthz DB probe. + pub healthz_timeout_ms: u64, + /// ENVIO_SERVE_WS_PING_INTERVAL_MS. How often idle WebSocket connections + /// are pinged; a connection that sends no pong/traffic within 2x this + /// interval is treated as dead and closed. Hasura's seconds-based + /// HASURA_GRAPHQL_WEBSOCKET_KEEPALIVE is accepted as a fallback. + pub ws_ping_interval_ms: u64, + /// ENVIO_SERVE_WS_CONNECTION_INIT_TIMEOUT_MS. Maximum time between the + /// WebSocket upgrade and a valid connection_init message. Hasura's + /// seconds-based HASURA_GRAPHQL_WEBSOCKET_CONNECTION_INIT_TIMEOUT is + /// accepted as a fallback. + pub ws_connection_init_timeout_ms: u64, + /// ENVIO_SERVE_WS_MAX_CONNECTIONS. Hard process-wide cap on upgraded + /// WebSocket connections, including connections still waiting for init. + pub ws_max_connections: usize, + /// ENVIO_SERVE_WS_MAX_OPERATIONS_PER_CONNECTION. Active GraphQL + /// operations allowed on one socket. + pub ws_max_operations_per_connection: usize, + /// ENVIO_SERVE_WS_MAX_OPERATIONS. Process-wide active WebSocket operation + /// cap. This bounds work even when an attacker spreads it across sockets. + pub ws_max_operations: usize, + /// ENVIO_SERVE_WS_MAX_CONCURRENT_POLLS. Maximum subscription polls that + /// may use the shared Postgres pool at once. + pub ws_max_concurrent_polls: usize, + /// ENVIO_SERVE_WS_POLL_INTERVAL_MS. Refetch interval for live and + /// streaming subscriptions. Also accepts Hasura's live-query interval + /// setting as a compatibility fallback. + pub ws_poll_interval_ms: u64, + /// ENVIO_SERVE_WS_MAX_MESSAGE_BYTES. Applied explicitly as both the axum + /// WebSocket message and frame limit. + pub ws_max_message_bytes: usize, +} + +/// deadpool_postgres::Config defaults to `cpu_core_count * 2` with no upper +/// bound; on a many-core host that lets that many full-response-buffered +/// queries (see exec/sql.rs) run concurrently, each holding its own copy of +/// the response in memory. Capping it keeps the default reasonable while +/// still scaling down on small hosts (e.g. a 2-core box gets 4, not 10). +const DEFAULT_POOL_MAX_SIZE_CAP: usize = 10; + +fn default_pool_max_size() -> usize { + let cpus = std::thread::available_parallelism().map_or(1, |n| n.get()); + std::cmp::min(cpus * 2, DEFAULT_POOL_MAX_SIZE_CAP) +} + +pub struct EnvReader { + dotenv: Option, + is_production: bool, +} + +impl EnvReader { + pub fn var(&self, name: &str) -> Option { + std::env::var(name) + .ok() + .filter(|v| !v.is_empty()) + .or_else(|| { + self.dotenv + .as_ref() + .and_then(|m| m.var(name).ok()) + .filter(|v| !v.is_empty()) + }) + } + + /// Env.res `devFallback`: the default only applies outside production. + fn var_dev_fallback(&self, name: &str, fallback: &str) -> anyhow::Result { + match self.var(name) { + Some(v) => Ok(v), + None if !self.is_production => Ok(fallback.to_string()), + None => Err(anyhow!( + "Missing required environment variable {name} (required when NODE_ENV=production)" + )), + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum PgSslMode { + Disable, + /// libpq `allow`/`prefer`: TLS if offered, plaintext fallback, no + /// certificate verification. + Prefer, + /// libpq `require`: TLS mandatory, no certificate verification. + Require, + /// libpq `verify-full` (also serving `verify-ca`, strictly — see the + /// module doc): TLS mandatory, chain + hostname verification against + /// the platform root CA store. + VerifyFull, +} + +impl PgSslMode { + pub fn as_str(&self) -> &'static str { + match self { + PgSslMode::Disable => "disable", + PgSslMode::Prefer => "prefer", + PgSslMode::Require => "require", + PgSslMode::VerifyFull => "verify-full", + } + } +} + +/// Unrecognized non-`false` values fall through to `VerifyFull`, preserving +/// the historical "any non-false value enables verified TLS" behavior for +/// configs written before the libpq mode names were supported. +fn parse_pg_ssl(raw: Option<&str>) -> PgSslMode { + match raw { + None | Some("false") | Some("disable") => PgSslMode::Disable, + Some("allow") | Some("prefer") => PgSslMode::Prefer, + Some("require") => PgSslMode::Require, + Some(_) => PgSslMode::VerifyFull, + } +} + +/// Millisecond-duration env vars share one convention: unset uses the +/// default, an explicit "0" disables the bound entirely. +fn parse_timeout_ms( + raw: Option, + name: &str, + default: Option, +) -> anyhow::Result> { + match raw { + None => Ok(default), + Some(v) => match v.parse::() { + Ok(0) => Ok(None), + Ok(n) => Ok(Some(n)), + Err(_) => Err(anyhow!( + "Invalid {name}: expected milliseconds as an integer" + )), + }, + } +} + +/// For bounds where 0 has no meaningful interpretation (a 0ms WS ping +/// interval would dead-check-close every connection instantly; a 0ms healthz +/// probe always fails): unset uses the default, 0 is a config error. +fn parse_positive_ms(raw: Option, name: &str, default: u64) -> anyhow::Result { + match raw { + None => Ok(default), + Some(v) => match v.parse::() { + Ok(0) => Err(anyhow!( + "Invalid {name}: must be greater than 0 milliseconds" + )), + Ok(n) => Ok(n), + Err(_) => Err(anyhow!( + "Invalid {name}: expected milliseconds as an integer" + )), + }, + } +} + +fn parse_startup_retry_budget_ms(raw: Option) -> anyhow::Result { + Ok(parse_timeout_ms(raw, "ENVIO_SERVE_STARTUP_RETRY_BUDGET_MS", Some(60_000))?.unwrap_or(0)) +} + +fn parse_positive_usize(raw: Option, name: &str, default: usize) -> anyhow::Result { + match raw { + None => Ok(default), + Some(v) => v + .parse::() + .ok() + .filter(|n| *n > 0) + .ok_or_else(|| anyhow!("Invalid {name}: must be a positive integer")), + } +} + +fn parse_ms_with_seconds_fallback( + milliseconds: Option, + seconds: Option, + milliseconds_name: &str, + seconds_name: &str, + default_ms: u64, +) -> anyhow::Result { + if milliseconds.is_some() { + return parse_positive_ms(milliseconds, milliseconds_name, default_ms); + } + let Some(value) = seconds else { + return Ok(default_ms); + }; + let seconds = value + .parse::() + .map_err(|_| anyhow!("Invalid {seconds_name}: expected seconds as an integer"))?; + if seconds == 0 { + return Err(anyhow!( + "Invalid {seconds_name}: must be greater than 0 seconds" + )); + } + seconds + .checked_mul(1_000) + .ok_or_else(|| anyhow!("Invalid {seconds_name}: duration is too large")) +} + +impl ServeEnv { + pub fn load(project_paths: &ParsedProjectPaths) -> anyhow::Result { + let dotenv = match dotenv::from_path(project_paths.project_root.join(".env")) { + Ok(map) => Some(map), + Err(dotenv::Error::Io(_, _)) => None, + Err(e) => return Err(e).context("Failed reading project .env file"), + }; + let is_production = std::env::var("NODE_ENV") + .map(|v| v == "production") + .unwrap_or(false); + let r = EnvReader { + dotenv, + is_production, + }; + + let pg_port = r + .var_dev_fallback("ENVIO_PG_PORT", "5433")? + .parse::() + .context("Invalid ENVIO_PG_PORT")?; + + let response_limit = match r + .var("ENVIO_HASURA_RESPONSE_LIMIT") + .or_else(|| r.var("HASURA_RESPONSE_LIMIT")) + { + Some(v) => Some( + v.parse::() + .context("Invalid ENVIO_HASURA_RESPONSE_LIMIT")?, + ), + None => None, + }; + + let pool_max_size = parse_positive_usize( + r.var("ENVIO_SERVE_POOL_MAX_SIZE"), + "ENVIO_SERVE_POOL_MAX_SIZE", + default_pool_max_size(), + )?; + let ws_max_operations_per_connection = parse_positive_usize( + r.var("ENVIO_SERVE_WS_MAX_OPERATIONS_PER_CONNECTION"), + "ENVIO_SERVE_WS_MAX_OPERATIONS_PER_CONNECTION", + 50, + )?; + let ws_max_operations = parse_positive_usize( + r.var("ENVIO_SERVE_WS_MAX_OPERATIONS"), + "ENVIO_SERVE_WS_MAX_OPERATIONS", + 1_000, + )?; + if ws_max_operations_per_connection > ws_max_operations { + return Err(anyhow!( + "ENVIO_SERVE_WS_MAX_OPERATIONS_PER_CONNECTION cannot exceed ENVIO_SERVE_WS_MAX_OPERATIONS" + )); + } + let ws_max_concurrent_polls = parse_positive_usize( + r.var("ENVIO_SERVE_WS_MAX_CONCURRENT_POLLS"), + "ENVIO_SERVE_WS_MAX_CONCURRENT_POLLS", + pool_max_size.saturating_sub(2).max(1), + )?; + if pool_max_size > 1 && ws_max_concurrent_polls >= pool_max_size { + return Err(anyhow!( + "ENVIO_SERVE_WS_MAX_CONCURRENT_POLLS must be smaller than ENVIO_SERVE_POOL_MAX_SIZE so HTTP retains database capacity" + )); + } + + Ok(ServeEnv { + pg_host: r.var_dev_fallback("ENVIO_PG_HOST", "localhost")?, + pg_port, + pg_user: r.var_dev_fallback("ENVIO_PG_USER", "postgres")?, + pg_password: r + .var("ENVIO_PG_PASSWORD") + .or_else(|| r.var("ENVIO_POSTGRES_PASSWORD")) + .unwrap_or_else(|| "testing".to_string()), + pg_database: r.var_dev_fallback("ENVIO_PG_DATABASE", "envio-dev")?, + pg_schema: r + .var("ENVIO_PG_SCHEMA") + .or_else(|| r.var("ENVIO_PG_PUBLIC_SCHEMA")) + .unwrap_or_else(|| "public".to_string()), + pg_ssl: parse_pg_ssl(r.var("ENVIO_PG_SSL_MODE").as_deref()), + admin_secret: r.var_dev_fallback("HASURA_GRAPHQL_ADMIN_SECRET", "testing")?, + response_limit, + aggregate_entities: parse_aggregate_entities( + r.var("ENVIO_HASURA_PUBLIC_AGGREGATE").as_deref(), + )?, + query_timeout_ms: parse_timeout_ms( + r.var("ENVIO_SERVE_QUERY_TIMEOUT_MS"), + "ENVIO_SERVE_QUERY_TIMEOUT_MS", + Some(120_000), + )?, + pool_wait_timeout_ms: parse_timeout_ms( + r.var("ENVIO_SERVE_POOL_WAIT_TIMEOUT_MS"), + "ENVIO_SERVE_POOL_WAIT_TIMEOUT_MS", + Some(15_000), + )?, + connect_timeout_ms: parse_timeout_ms( + r.var("ENVIO_SERVE_CONNECT_TIMEOUT_MS"), + "ENVIO_SERVE_CONNECT_TIMEOUT_MS", + Some(10_000), + )?, + pool_max_size, + startup_retry_budget_ms: parse_startup_retry_budget_ms( + r.var("ENVIO_SERVE_STARTUP_RETRY_BUDGET_MS"), + )?, + healthz_timeout_ms: parse_positive_ms( + r.var("ENVIO_SERVE_HEALTHZ_TIMEOUT_MS"), + "ENVIO_SERVE_HEALTHZ_TIMEOUT_MS", + 2_000, + )?, + ws_ping_interval_ms: parse_ms_with_seconds_fallback( + r.var("ENVIO_SERVE_WS_PING_INTERVAL_MS"), + r.var("HASURA_GRAPHQL_WEBSOCKET_KEEPALIVE"), + "ENVIO_SERVE_WS_PING_INTERVAL_MS", + "HASURA_GRAPHQL_WEBSOCKET_KEEPALIVE", + 10_000, + )?, + ws_connection_init_timeout_ms: parse_ms_with_seconds_fallback( + r.var("ENVIO_SERVE_WS_CONNECTION_INIT_TIMEOUT_MS"), + r.var("HASURA_GRAPHQL_WEBSOCKET_CONNECTION_INIT_TIMEOUT"), + "ENVIO_SERVE_WS_CONNECTION_INIT_TIMEOUT_MS", + "HASURA_GRAPHQL_WEBSOCKET_CONNECTION_INIT_TIMEOUT", + 3_000, + )?, + ws_max_connections: parse_positive_usize( + r.var("ENVIO_SERVE_WS_MAX_CONNECTIONS"), + "ENVIO_SERVE_WS_MAX_CONNECTIONS", + 1_000, + )?, + ws_max_operations_per_connection, + ws_max_operations, + ws_max_concurrent_polls, + ws_poll_interval_ms: parse_positive_ms( + r.var("ENVIO_SERVE_WS_POLL_INTERVAL_MS") + .or_else(|| r.var("HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_REFETCH_INTERVAL")), + "ENVIO_SERVE_WS_POLL_INTERVAL_MS", + 1_000, + )?, + ws_max_message_bytes: parse_positive_usize( + r.var("ENVIO_SERVE_WS_MAX_MESSAGE_BYTES"), + "ENVIO_SERVE_WS_MAX_MESSAGE_BYTES", + 1024 * 1024, + )?, + }) + } + + /// The config.yaml `schema` field default and resolution live in + /// project_schema.rs; this reader is only env vars. + /// + /// TLS behavior per `pg_ssl` mode is described on the module doc and + /// `PgSslMode`. + pub fn make_pg_pool(&self) -> anyhow::Result { + let mut cfg = deadpool_postgres::Config::new(); + cfg.host = Some(self.pg_host.clone()); + cfg.port = Some(self.pg_port); + cfg.user = Some(self.pg_user.clone()); + cfg.password = Some(self.pg_password.clone()); + cfg.dbname = Some(self.pg_database.clone()); + // Serialization parity depends on ISO datestyle and UTC output for + // timestamptz values; pin them per connection. statement_timeout + // makes Postgres itself cancel over-budget queries (SQLSTATE 57014) + // — the client-side wrap in exec::sql only fires when the server + // can't respond at all (frozen/unreachable). + let mut options = "-c TimeZone=UTC -c DateStyle=ISO".to_string(); + if let Some(ms) = self.query_timeout_ms { + options.push_str(&format!(" -c statement_timeout={ms}")); + } + cfg.options = Some(options); + cfg.connect_timeout = self.connect_timeout_ms.map(Duration::from_millis); + // Unbounded pool waits turn a wedged Postgres into a permanently + // hung server: once every connection is checked out by a stuck + // query, all later requests queue forever. A wait timeout converts + // that into a clean per-request error instead. + let mut pool_cfg = deadpool_postgres::PoolConfig::new(self.pool_max_size); + pool_cfg.timeouts.wait = self.pool_wait_timeout_ms.map(Duration::from_millis); + pool_cfg.timeouts.create = self.connect_timeout_ms.map(Duration::from_millis); + cfg.pool = Some(pool_cfg); + + match self.pg_ssl { + PgSslMode::Disable => { + let pool = cfg + .create_pool( + Some(deadpool_postgres::Runtime::Tokio1), + tokio_postgres::NoTls, + ) + .context("Failed creating Postgres connection pool")?; + Ok(pool) + } + PgSslMode::Prefer => { + cfg.ssl_mode = Some(deadpool_postgres::SslMode::Prefer); + make_tls_pool(&cfg, no_verify_tls_config()) + } + PgSslMode::Require => { + cfg.ssl_mode = Some(deadpool_postgres::SslMode::Require); + make_tls_pool(&cfg, no_verify_tls_config()) + } + PgSslMode::VerifyFull => { + cfg.ssl_mode = Some(deadpool_postgres::SslMode::Require); + make_tls_pool(&cfg, verified_tls_config(native_root_certs()?)) + } + } + } +} + +/// Loads the platform's trusted root CA store (e.g. `/etc/ssl/certs` on +/// Linux, the Keychain on macOS, the Windows certificate store) for +/// verifying the Postgres server certificate. +fn native_root_certs() -> anyhow::Result { + let result = rustls_native_certs::load_native_certs(); + let mut roots = rustls::RootCertStore::empty(); + let (added, _skipped) = roots.add_parsable_certificates(result.certs); + if added == 0 { + return Err(anyhow!( + "Failed loading the system's trusted root CA store for Postgres TLS: {:?}", + result.errors + )); + } + Ok(roots) +} + +// rustls 0.23 needs a process-wide crypto provider installed before any +// ClientConfig can be built. install_default() errors if one is already +// installed (e.g. by another TLS client sharing this process) -- that's +// fine, we only need *a* provider present, not necessarily this call's. +fn ensure_crypto_provider() { + let _ = rustls::crypto::ring::default_provider().install_default(); +} + +fn verified_tls_config(roots: rustls::RootCertStore) -> rustls::ClientConfig { + ensure_crypto_provider(); + rustls::ClientConfig::builder() + .with_root_certificates(roots) + .with_no_client_auth() +} + +/// Encryption-without-authentication, for the libpq `allow`/`prefer`/ +/// `require` modes: any server certificate (self-signed, expired, wrong +/// hostname) is accepted, but the TLS record layer -- including handshake +/// signature checks binding the session to the presented key -- still runs +/// normally. Never used for `verify-ca`/`verify-full`. +fn no_verify_tls_config() -> rustls::ClientConfig { + ensure_crypto_provider(); + let provider = rustls::crypto::CryptoProvider::get_default() + .expect("crypto provider installed above") + .clone(); + rustls::ClientConfig::builder() + .dangerous() + .with_custom_certificate_verifier(std::sync::Arc::new(AcceptAnyServerCert { provider })) + .with_no_client_auth() +} + +#[derive(Debug)] +struct AcceptAnyServerCert { + provider: std::sync::Arc, +} + +impl rustls::client::danger::ServerCertVerifier for AcceptAnyServerCert { + fn verify_server_cert( + &self, + _end_entity: &rustls::pki_types::CertificateDer<'_>, + _intermediates: &[rustls::pki_types::CertificateDer<'_>], + _server_name: &rustls::pki_types::ServerName<'_>, + _ocsp_response: &[u8], + _now: rustls::pki_types::UnixTime, + ) -> Result { + Ok(rustls::client::danger::ServerCertVerified::assertion()) + } + + // Handshake signatures are still verified against the presented + // certificate's key: skipping *identity* verification must not also + // skip proof that the peer holds the key it presented. + fn verify_tls12_signature( + &self, + message: &[u8], + cert: &rustls::pki_types::CertificateDer<'_>, + dss: &rustls::DigitallySignedStruct, + ) -> Result { + rustls::crypto::verify_tls12_signature( + message, + cert, + dss, + &self.provider.signature_verification_algorithms, + ) + } + + fn verify_tls13_signature( + &self, + message: &[u8], + cert: &rustls::pki_types::CertificateDer<'_>, + dss: &rustls::DigitallySignedStruct, + ) -> Result { + rustls::crypto::verify_tls13_signature( + message, + cert, + dss, + &self.provider.signature_verification_algorithms, + ) + } + + fn supported_verify_schemes(&self) -> Vec { + self.provider + .signature_verification_algorithms + .supported_schemes() + } +} + +/// Split out from `make_pg_pool` so tests can exercise a real TLS handshake +/// against a throwaway CA instead of the machine's real trust store. +fn make_tls_pool( + cfg: &deadpool_postgres::Config, + tls_config: rustls::ClientConfig, +) -> anyhow::Result { + let tls = tokio_postgres_rustls::MakeRustlsConnect::new(tls_config); + cfg.create_pool(Some(deadpool_postgres::Runtime::Tokio1), tls) + .context("Failed creating Postgres TLS connection pool") +} + +/// Mirrors Env.res ENVIO_HASURA_PUBLIC_AGGREGATE: a JSON array of entity +/// names, with a legacy `a&b&c` string form. +fn parse_aggregate_entities(raw: Option<&str>) -> anyhow::Result> { + let Some(raw) = raw else { + return Ok(vec![]); + }; + if let Ok(list) = serde_json::from_str::>(raw) { + return Ok(list); + } + let parts: Vec<&str> = raw.split('&').collect(); + if parts.len() >= 2 { + return Ok(parts.into_iter().map(|s| s.to_string()).collect()); + } + Err(anyhow!( + "Invalid ENVIO_HASURA_PUBLIC_AGGREGATE: provide an array of entities in the JSON format" + )) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::io::BufReader; + use std::process::Command; + + #[test] + fn parse_pg_ssl_env_var() { + use PgSslMode::*; + assert_eq!( + [ + parse_pg_ssl(None), + parse_pg_ssl(Some("false")), + parse_pg_ssl(Some("disable")), + parse_pg_ssl(Some("allow")), + parse_pg_ssl(Some("prefer")), + parse_pg_ssl(Some("require")), + parse_pg_ssl(Some("verify-ca")), + parse_pg_ssl(Some("verify-full")), + parse_pg_ssl(Some("true")), + parse_pg_ssl(Some("")), + parse_pg_ssl(Some("bogus")), + ], + [ + Disable, Disable, Disable, Prefer, Prefer, Require, VerifyFull, VerifyFull, + VerifyFull, VerifyFull, VerifyFull, + ], + ); + } + + #[test] + fn parse_positive_ms_rejects_zero() { + assert_eq!( + [ + parse_positive_ms(None, "X", 7).ok(), + parse_positive_ms(Some("42".to_string()), "X", 7).ok(), + parse_positive_ms(Some("0".to_string()), "X", 7).ok(), + parse_positive_ms(Some("nope".to_string()), "X", 7).ok(), + ], + [Some(7), Some(42), None, None], + ); + assert_eq!( + parse_positive_ms(Some("0".to_string()), "ENVIO_SERVE_WS_PING_INTERVAL_MS", 7) + .unwrap_err() + .to_string(), + "Invalid ENVIO_SERVE_WS_PING_INTERVAL_MS: must be greater than 0 milliseconds" + ); + } + + #[test] + fn startup_retry_budget_accepts_zero_as_fail_fast() { + assert_eq!( + [ + parse_startup_retry_budget_ms(None).ok(), + parse_startup_retry_budget_ms(Some("42".to_string())).ok(), + parse_startup_retry_budget_ms(Some("0".to_string())).ok(), + parse_startup_retry_budget_ms(Some("nope".to_string())).ok(), + ], + [Some(60_000), Some(42), Some(0), None], + ); + } + + #[test] + fn parse_positive_usize_rejects_zero_and_invalid_values() { + assert_eq!( + [ + parse_positive_usize(None, "X", 7).ok(), + parse_positive_usize(Some("42".to_string()), "X", 7).ok(), + parse_positive_usize(Some("0".to_string()), "X", 7).ok(), + parse_positive_usize(Some("-1".to_string()), "X", 7).ok(), + parse_positive_usize(Some("nope".to_string()), "X", 7).ok(), + ], + [Some(7), Some(42), None, None, None], + ); + } + + #[test] + fn hasura_websocket_seconds_fallback_converts_to_milliseconds() { + assert_eq!( + parse_ms_with_seconds_fallback( + None, + Some("3".to_string()), + "ENVIO_MS", + "HASURA_SECONDS", + 7, + ) + .unwrap(), + 3_000 + ); + assert_eq!( + parse_ms_with_seconds_fallback( + Some("25".to_string()), + Some("3".to_string()), + "ENVIO_MS", + "HASURA_SECONDS", + 7, + ) + .unwrap(), + 25, + "Envio's millisecond setting has precedence" + ); + assert!(parse_ms_with_seconds_fallback( + None, + Some("0".to_string()), + "ENVIO_MS", + "HASURA_SECONDS", + 7, + ) + .is_err()); + } + + #[test] + fn loads_system_root_ca_store() { + // Exercises the exact cert-loading call `make_pg_pool` makes for + // `pg_ssl`, without a live handshake: every dev machine and CI + // runner has *some* trusted root CAs installed, so this should + // always succeed. + let roots = native_root_certs().expect("system CA store should load"); + assert!(!roots.is_empty()); + } + + /// Full round-trip against a real, throwaway, SSL-enabled Postgres + /// container: a client trusting the test CA completes the handshake and + /// queries the server, while the same server is rejected when verified + /// against the *real* system CA store -- proving TLS verification is + /// actually enforced rather than silently skipped. + /// + /// Spins up its own `postgres:16` container on a Docker-assigned port + /// (never the shared dev instance on 5433) and always tears it down. + /// Skips (doesn't fail) if Docker isn't available in this environment. + #[test] + fn tls_connection_verifies_server_certificate() { + if super::super::test_support::skip_without_docker() { + return; + } + + let container = TestTlsPostgres::start(); + + let rt = tokio::runtime::Runtime::new().unwrap(); + rt.block_on(async { + let mut cfg = deadpool_postgres::Config::new(); + cfg.host = Some("localhost".to_string()); + cfg.port = Some(container.port); + cfg.user = Some("postgres".to_string()); + cfg.password = Some("testing".to_string()); + cfg.dbname = Some("envio-dev".to_string()); + cfg.ssl_mode = Some(deadpool_postgres::SslMode::Require); + + let trusted_roots = load_pem_roots(&container.ca_cert_pem); + let pool = + make_tls_pool(&cfg, verified_tls_config(trusted_roots)).expect("pool construction"); + // pg_isready accepting TCP doesn't guarantee the TLS listener + // is immediately ready to complete a handshake under load; a + // couple of retries absorbs that startup race without masking + // a real connectivity failure. + let mut client = None; + for attempt in 0..5 { + match pool.get().await { + Ok(c) => { + client = Some(c); + break; + } + Err(_) if attempt < 4 => { + std::thread::sleep(std::time::Duration::from_millis(500)) + } + Err(e) => { + panic!("connecting with the issuing test CA trusted should succeed: {e}") + } + } + } + let client = client.unwrap(); + let row = client.query_one("select 1", &[]).await.expect("query"); + assert_eq!(row.get::<_, i32>(0), 1); + + let system_roots = native_root_certs().expect("system CA store should load"); + let pool = + make_tls_pool(&cfg, verified_tls_config(system_roots)).expect("pool construction"); + let connect_result = pool.get().await; + assert!( + connect_result.is_err(), + "connecting to a self-signed cert absent from the system trust store must fail" + ); + + // `require` semantics: TLS is used but the untrusted certificate + // is accepted, so the same server that verify-full just rejected + // is reachable. + let pool = make_tls_pool(&cfg, no_verify_tls_config()).expect("pool construction"); + let client = pool + .get() + .await + .expect("sslmode=require must accept a self-signed certificate"); + let row = client.query_one("select 1", &[]).await.expect("query"); + assert_eq!(row.get::<_, i32>(0), 1); + }); + } + + fn load_pem_roots(pem: &str) -> rustls::RootCertStore { + let mut reader = BufReader::new(pem.as_bytes()); + let der = rustls_pemfile::certs(&mut reader).expect("parse test CA PEM"); + let mut roots = rustls::RootCertStore::empty(); + let (added, _skipped) = roots.add_parsable_certificates( + der.into_iter().map(rustls::pki_types::CertificateDer::from), + ); + assert_eq!(added, 1); + roots + } + + /// A throwaway `postgres:16` container with SSL enabled behind a + /// self-signed test CA, torn down on drop (including on test panic). + struct TestTlsPostgres { + name: String, + volume: String, + port: u16, + ca_cert_pem: String, + } + + impl TestTlsPostgres { + fn start() -> Self { + let id = format!( + "{}-{}", + std::process::id(), + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos() + ); + let name = format!("envio-serve-tls-test-{id}"); + let volume = format!("envio-serve-tls-test-certs-{id}"); + + let dir = tempdir::TempDir::new("envio-serve-tls-test").unwrap(); + let (ca_cert_pem, server_crt, server_key) = generate_self_signed_cert(dir.path()); + + run(Command::new("docker").args(["volume", "create", &volume])); + run(Command::new("docker").args([ + "run", + "--rm", + "-v", + &format!("{volume}:/certs"), + "-v", + &format!("{}:/src:ro", dir.path().display()), + "alpine", + "sh", + "-c", + &format!( + "cp /src/{} /src/{} /certs/ && chown 999:999 /certs/{} /certs/{} && chmod 600 /certs/{}", + server_crt, server_key, server_crt, server_key, server_key + ), + ])); + + run(Command::new("docker").args([ + "run", + "-d", + "--name", + &name, + "-e", + "POSTGRES_PASSWORD=testing", + "-e", + "POSTGRES_USER=postgres", + "-e", + "POSTGRES_DB=envio-dev", + "-p", + "127.0.0.1::5432", + "-v", + &format!("{volume}:/certs:ro"), + "postgres:16", + "-c", + "ssl=on", + "-c", + &format!("ssl_cert_file=/certs/{server_crt}"), + "-c", + &format!("ssl_key_file=/certs/{server_key}"), + ])); + + let port_output = run(Command::new("docker").args(["port", &name, "5432"])); + let port = String::from_utf8_lossy(&port_output.stdout) + .lines() + .next() + .and_then(|line| line.rsplit(':').next()) + .and_then(|p| p.trim().parse::().ok()) + .expect("docker port output should contain the mapped host port"); + + let container = TestTlsPostgres { + name: name.clone(), + volume, + port, + ca_cert_pem, + }; + + for _ in 0..30 { + let ready = Command::new("docker") + .args(["exec", &name, "pg_isready", "-U", "postgres"]) + .output() + .map(|o| o.status.success()) + .unwrap_or(false); + if ready { + return container; + } + std::thread::sleep(std::time::Duration::from_millis(500)); + } + panic!("test Postgres container did not become ready in time"); + } + } + + impl Drop for TestTlsPostgres { + fn drop(&mut self) { + let _ = Command::new("docker") + .args(["rm", "-f", &self.name]) + .output(); + let _ = Command::new("docker") + .args(["volume", "rm", "-f", &self.volume]) + .output(); + } + } + + fn run(cmd: &mut Command) -> std::process::Output { + let output = cmd.output().expect("failed to run docker"); + assert!( + output.status.success(), + "docker command failed: {} {}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + output + } + + /// Generates a throwaway CA + server cert/key pair via the system + /// `openssl` CLI, returning (ca_cert_pem, server_crt_filename, + /// server_key_filename) with the cert/key files written into `dir`. + fn generate_self_signed_cert(dir: &std::path::Path) -> (String, String, String) { + let openssl = |args: &[&str]| { + let output = Command::new("openssl") + .args(args) + .current_dir(dir) + .output() + .expect("failed to run openssl"); + assert!( + output.status.success(), + "openssl {:?} failed: {}", + args, + String::from_utf8_lossy(&output.stderr) + ); + }; + + openssl(&["genrsa", "-out", "ca.key", "2048"]); + openssl(&[ + "req", + "-x509", + "-new", + "-nodes", + "-key", + "ca.key", + "-sha256", + "-days", + "2", + "-out", + "ca.crt", + "-subj", + "/CN=envio-serve-test-ca", + ]); + openssl(&["genrsa", "-out", "server.key", "2048"]); + openssl(&[ + "req", + "-new", + "-key", + "server.key", + "-out", + "server.csr", + "-subj", + "/CN=localhost", + ]); + // Plain `openssl x509 -req` with no extensions emits an X.509v1 + // certificate, which rustls-webpki rejects outright + // (UnsupportedCertVersion) regardless of trust — v3 with a SAN is + // required both to pass that check and for hostname verification. + std::fs::write( + dir.join("server.ext"), + "basicConstraints=CA:FALSE\nsubjectAltName=DNS:localhost\n", + ) + .unwrap(); + openssl(&[ + "x509", + "-req", + "-in", + "server.csr", + "-CA", + "ca.crt", + "-CAkey", + "ca.key", + "-CAcreateserial", + "-out", + "server.crt", + "-days", + "2", + "-sha256", + "-extfile", + "server.ext", + ]); + + let ca_cert_pem = std::fs::read_to_string(dir.join("ca.crt")).unwrap(); + ( + ca_cert_pem, + "server.crt".to_string(), + "server.key".to_string(), + ) + } +} diff --git a/packages/cli/src/serve/exec/error.rs b/packages/cli/src/serve/exec/error.rs new file mode 100644 index 0000000000..95cf59cf62 --- /dev/null +++ b/packages/cli/src/serve/exec/error.rs @@ -0,0 +1,88 @@ +//! Hasura-shaped GraphQL errors. +//! +//! Hasura returns HTTP 200 with `{"errors": [{"message", "extensions": +//! {"path", "code"}}]}` for essentially everything, including a wrong +//! admin secret and malformed request bodies (verified live: none of these +//! use a non-200 status). Messages are matched byte-for-byte against the +//! oracle snapshots. + +use serde_json::json; + +#[derive(Debug, Clone)] +pub struct GraphQLError { + pub message: String, + /// JSONPath-ish location, e.g. `$.selectionSet.User.args.limit`. + pub path: String, + pub code: &'static str, + pub status: u16, +} + +pub const CODE_VALIDATION_FAILED: &str = "validation-failed"; +pub const CODE_PARSE_FAILED: &str = "parse-failed"; +pub const CODE_UNEXPECTED_PAYLOAD: &str = "unexpected-payload"; +pub const CODE_ACCESS_DENIED: &str = "access-denied"; +pub const CODE_POSTGRES_ERROR: &str = "postgres-error"; +pub const CODE_UNEXPECTED: &str = "unexpected"; + +pub const QUERY_TIMEOUT_MESSAGE: &str = "database query timeout"; + +impl GraphQLError { + pub fn validation(path: impl Into, message: impl Into) -> GraphQLError { + GraphQLError { + message: message.into(), + path: path.into(), + code: CODE_VALIDATION_FAILED, + status: 200, + } + } + + pub fn query_timeout() -> GraphQLError { + GraphQLError { + message: QUERY_TIMEOUT_MESSAGE.to_string(), + path: "$".to_string(), + code: CODE_UNEXPECTED, + status: 200, + } + } + + /// Connection-level infrastructure failure (Postgres unreachable, pool + /// exhausted, query timed out) — retryable, unlike deterministic query + /// errors, which reproduce on every attempt. + pub fn is_transient_infra(&self) -> bool { + self.code == CODE_POSTGRES_ERROR || self.message == QUERY_TIMEOUT_MESSAGE + } + + pub fn unexpected_payload(message: impl Into) -> GraphQLError { + GraphQLError { + message: message.into(), + path: "$".to_string(), + code: CODE_UNEXPECTED_PAYLOAD, + status: 200, + } + } + + pub fn access_denied() -> GraphQLError { + GraphQLError { + message: "invalid \"x-hasura-admin-secret\"/\"x-hasura-access-key\"".to_string(), + path: "$".to_string(), + code: CODE_ACCESS_DENIED, + status: 200, + } + } + + pub fn to_json(&self) -> serde_json::Value { + json!({ + "message": self.message, + "extensions": { + "path": self.path, + "code": self.code, + } + }) + } + + pub fn response_body(&self) -> serde_json::Value { + json!({ "errors": [self.to_json()] }) + } +} + +pub type GResult = Result; diff --git a/packages/cli/src/serve/exec/ir.rs b/packages/cli/src/serve/exec/ir.rs new file mode 100644 index 0000000000..a3d1a36e0d --- /dev/null +++ b/packages/cli/src/serve/exec/ir.rs @@ -0,0 +1,378 @@ +//! Intermediate representation of a validated GraphQL operation, produced +//! by `validate.rs` and consumed by `sql.rs`/`executor`. Everything here is +//! fully resolved: aliases, db column names, coerced argument values. + +// Several fields (StreamCursor typing, selection table names) are populated +// by the planner but only read by the WS subscription executor, which is +// not implemented yet. +#![allow(dead_code)] + +use crate::serve::model::Scalar; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum OperationKind { + Query, + Subscription, +} + +#[derive(Debug)] +pub struct Operation { + pub kind: OperationKind, + pub root_fields: Vec, +} + +// Table is the overwhelmingly common variant; boxing it would cost an +// allocation per root field for no benefit. +#[allow(clippy::large_enum_variant)] +#[derive(Debug)] +pub enum RootField { + /// `__typename` on the root: resolves to "query_root"/"subscription_root". + Typename { alias: String }, + /// `__schema` / `__type` — resolved in-memory against the registry. + /// The raw selection tree is kept for the introspection resolver. + Introspection(IntrospectionField), + /// A table root field, executed as one SQL statement. + Table(TableRoot), +} + +#[derive(Debug)] +pub struct IntrospectionField { + pub alias: String, + /// "__schema" or "__type" + pub field: String, + /// For `__type(name: ...)`. + pub type_name: Option, + pub selection: IntroSelection, +} + +/// Selection tree for introspection resolution: pre-validated field names +/// on the __Schema/__Type/__Field/... meta types. +#[derive(Debug)] +pub struct IntroSelection { + pub items: Vec, +} + +#[derive(Debug)] +pub struct IntroSelItem { + pub alias: String, + pub field: String, + /// includeDeprecated for fields()/enumValues(); name for __type-like args. + pub include_deprecated: bool, + pub selection: Option, +} + +#[derive(Debug)] +pub struct TableRoot { + pub alias: String, + pub table: String, + pub kind: TableRootKind, +} + +#[derive(Debug)] +pub enum TableRootKind { + /// `(...) : [T!]!` + Many { + args: SelectArgs, + selection: ObjectSelection, + }, + /// `_by_pk(...)` + ByPk { + /// (db column, value) pairs. + pk: Vec<(String, SqlValue)>, + selection: ObjectSelection, + }, + /// `_aggregate(...)` + Aggregate { + args: SelectArgs, + selection: AggregateSelection, + }, + /// `_stream(...)` — subscriptions only. + Stream { + batch_size: i64, + cursor: Vec, + where_: Option, + selection: ObjectSelection, + }, +} + +#[derive(Debug)] +pub struct StreamCursor { + /// db column name + pub column: String, + /// Complete SQL cast for cursor parameters, including array suffix and + /// any required custom-type namespace qualification. + pub cast: String, + pub initial_value: Option, + pub descending: bool, +} + +/// Selection over a table object type. +#[derive(Debug)] +pub struct ObjectSelection { + pub table: String, + pub items: Vec, +} + +#[derive(Debug)] +pub enum SelItem { + Typename { + alias: String, + /// The GraphQL object type name to return. + type_name: String, + }, + Column { + alias: String, + /// db column name + column: String, + scalar: Scalar, + pg_type: String, + is_array: bool, + /// For json/jsonb columns: the parsed `path` argument as a Postgres + /// #> path (list of keys/indexes), if provided. + json_path: Option>, + }, + ObjectRel { + alias: String, + /// db column on the parent joined to remote id + local_column: String, + remote_table: String, + selection: ObjectSelection, + }, + ArrayRel { + alias: String, + /// db column on the remote table joined to parent id + remote_column: String, + remote_table: String, + args: SelectArgs, + selection: ObjectSelection, + }, + ArrayRelAggregate { + alias: String, + remote_column: String, + remote_table: String, + args: SelectArgs, + selection: AggregateSelection, + }, +} + +#[derive(Debug)] +pub struct AggregateSelection { + pub table: String, + pub items: Vec, + /// The public role's response limit caps the rows returned by `nodes` + /// while the aggregate itself is computed over the uncapped set. + pub nodes_limit: Option, +} + +#[derive(Debug)] +pub enum AggSelItem { + Typename { + alias: String, + type_name: String, + }, + /// The `aggregate` field. + Aggregate { + alias: String, + items: Vec, + }, + /// The `nodes` field. + Nodes { + alias: String, + selection: ObjectSelection, + }, +} + +#[derive(Debug)] +pub enum AggFieldItem { + Typename { + alias: String, + type_name: String, + }, + Count { + alias: String, + /// db column names; empty means count(*) + columns: Vec, + distinct: bool, + }, + /// sum/avg/min/max/stddev/... with its column sub-selection. + Op { + alias: String, + op: String, + columns: Vec, + }, +} + +#[derive(Debug)] +pub enum AggOpColumn { + Typename { + alias: String, + type_name: String, + }, + Column { + alias: String, + /// db column name + column: String, + scalar: Scalar, + pg_type: String, + is_array: bool, + op: String, + }, +} + +#[derive(Debug, Default)] +pub struct SelectArgs { + pub where_: Option, + pub order_by: Vec, + pub limit: Option, + pub offset: Option, + /// db column names + pub distinct_on: Vec, +} + +#[derive(Debug)] +pub struct OrderByItem { + pub target: OrderTarget, + pub direction: OrderDirection, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum OrderDirection { + Asc, + AscNullsFirst, + AscNullsLast, + Desc, + DescNullsFirst, + DescNullsLast, +} + +#[derive(Debug)] +pub enum OrderTarget { + /// Order by a column of the current table (db name). + Column { column: String }, + /// Order by a column reached through a chain of object relationships. + /// Each step is (local db column, remote table). + ObjectRelColumn { + path: Vec<(String, String)>, + column: String, + }, + /// Order by an aggregate of an array relationship: + /// `tokens_aggregate: {count: desc}` or `{max: {tokenId: asc}}`. + /// A chain of object-relationship steps may precede the final + /// array-relationship hop. + ArrayRelAggregate { + path: Vec<(String, String)>, + /// (remote db column on the array rel's table, remote table) + remote_column: String, + remote_table: String, + /// count / max / min / sum / avg / ... + op: String, + /// db column for per-column ops; None for count. + column: Option, + }, +} + +#[derive(Debug)] +pub enum BoolExp { + And(Vec), + Or(Vec), + Not(Box), + /// One comparison-exp entry on a column, e.g. `id: {_eq: "x", _gt: "y"}` + /// becomes two Compare nodes. + Compare { + /// db column name + column: String, + scalar: Scalar, + pg_type: String, + is_array: bool, + op: CompareOp, + }, + /// Filter through an object relationship. + ObjectRel { + local_column: String, + remote_table: String, + exp: Box, + }, + /// EXISTS through an array relationship. + ArrayRel { + remote_column: String, + remote_table: String, + exp: Box, + }, + /// Aggregate predicate through an array relationship + /// (`_aggregate: {count: {predicate: {_gt: 0}}}`). + ArrayRelAggregate { + remote_column: String, + remote_table: String, + pred: AggregatePredicate, + }, +} + +#[derive(Debug)] +pub struct AggregatePredicate { + /// count / bool_and / bool_or + pub op: String, + /// db columns for count arguments + pub columns: Vec, + pub distinct: bool, + pub filter: Option>, + /// The comparison on the aggregate result (Int/Boolean comparison exp). + pub predicate: Vec, +} + +#[derive(Debug)] +pub enum CompareOp { + Eq(SqlValue), + Neq(SqlValue), + Gt(SqlValue), + Gte(SqlValue), + Lt(SqlValue), + Lte(SqlValue), + In(Vec), + Nin(Vec), + IsNull(bool), + Like(SqlValue), + Nlike(SqlValue), + Ilike(SqlValue), + Nilike(SqlValue), + Similar(SqlValue), + Nsimilar(SqlValue), + Regex(SqlValue), + Iregex(SqlValue), + Nregex(SqlValue), + Niregex(SqlValue), + /// jsonb / array operators + Contains(SqlValue), + ContainedIn(SqlValue), + HasKey(SqlValue), + HasKeysAll(Vec), + HasKeysAny(Vec), + /// jsonb _cast: (String: String_comparison_exp) — compare col::text. + CastText(Vec), +} + +/// A coerced scalar value ready to bind as a SQL parameter. Values are +/// carried as their Postgres text representation and cast to the right +/// type in SQL (`$1::numeric` etc.), which sidesteps binary encoding for +/// exotic types entirely. +#[derive(Clone, Debug)] +pub struct SqlValue { + pub text: Option, + /// Cast target, e.g. "text", "int4", "numeric", "jsonb", an enum type + /// name, or "text[]" for array values (text form `{a,b}`). + pub cast: String, +} + +impl SqlValue { + pub fn new(text: impl Into, cast: impl Into) -> SqlValue { + SqlValue { + text: Some(text.into()), + cast: cast.into(), + } + } + pub fn null(cast: impl Into) -> SqlValue { + SqlValue { + text: None, + cast: cast.into(), + } + } +} diff --git a/packages/cli/src/serve/exec/mod.rs b/packages/cli/src/serve/exec/mod.rs new file mode 100644 index 0000000000..917cf7974a --- /dev/null +++ b/packages/cli/src/serve/exec/mod.rs @@ -0,0 +1,412 @@ +//! Request execution pipeline: parse → validate/plan → execute → respond. + +pub mod error; +pub mod ir; +pub mod sql; +pub mod validate; + +use crate::serve::gql::schema_build::{Role, RoleSchema}; +use crate::serve::gql::{introspection, schema_build}; +use crate::serve::ServeState; +use error::GraphQLError; +use serde::Deserialize; +use std::hash::{Hash, Hasher}; +use std::sync::Arc; + +#[derive(Deserialize, Clone)] +pub struct GraphQLRequest { + pub query: Option, + #[serde(default)] + pub variables: Option, + #[serde(default, rename = "operationName")] + pub operation_name: Option, + /// Trusted decoder metadata for JSON variable numbers that cannot be + /// represented losslessly by serde_json's default number model. This is + /// deliberately kept outside `variables` so a client cannot forge it. + #[serde(skip)] + pub(crate) variable_number_originals: std::collections::HashMap, +} + +/// Where the request came from — determines which operation types are +/// admissible (Hasura rejects subscriptions over HTTP before validating +/// their selection sets). +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum Transport { + Http, + Ws, +} + +pub struct Schemas { + pub admin: RoleSchema, + pub public: RoleSchema, +} + +impl Schemas { + pub fn build(model: &crate::serve::model::ServerModel) -> Schemas { + Schemas { + admin: RoleSchema { + registry: schema_build::build(model, Role::Admin), + role: Role::Admin, + }, + public: RoleSchema { + registry: schema_build::build(model, Role::Public), + role: Role::Public, + }, + } + } + + pub fn for_role(&self, role: Role) -> &RoleSchema { + match role { + Role::Admin => &self.admin, + Role::Public => &self.public, + } + } +} + +/// Executes one GraphQL request over HTTP semantics. Returns (status, +/// response JSON as a string). The response is assembled by string +/// splicing so values produced by Postgres keep their exact serialization. +pub async fn execute_query_request( + state: &Arc, + schemas: &Schemas, + role: Role, + request: &GraphQLRequest, +) -> (u16, String) { + match execute_inner(state, schemas, role, request).await { + Ok(body) => (200, body), + Err(e) => (e.status, e.response_body().to_string()), + } +} + +async fn execute_inner( + state: &Arc, + schemas: &Schemas, + role: Role, + request: &GraphQLRequest, +) -> Result { + let schema = schemas.for_role(role); + let operation = validate::plan_request(&state.model, schema, request, Transport::Http)?; + execute_operation(state, schema, &operation).await +} + +/// Bounds `fut` by the whole-operation client-side query timeout, if one is +/// configured. Shared by every operation entry point so the timeout always +/// covers the whole operation — every root field's pool wait + prepare + +/// query — rather than each one individually, which would let an operation +/// with N root fields hang for N budgets. +async fn with_query_timeout( + state: &Arc, + fut: impl std::future::Future>, +) -> Result { + match state.query_timeout { + None => fut.await, + Some(limit) => tokio::time::timeout(limit, fut) + .await + .unwrap_or_else(|_| Err(GraphQLError::query_timeout())), + } +} + +/// Executes an already-planned (non-subscription) operation. +pub async fn execute_operation( + state: &Arc, + schema: &RoleSchema, + operation: &ir::Operation, +) -> Result { + with_query_timeout(state, execute_operation_inner(state, schema, operation)).await +} + +/// Identity of one ordinary live-query cohort. The response alias is not +/// part of the key: subscribers may spell the same root differently while +/// sharing the exact same database result. Role remains explicit even when +/// two role-specific plans happen to compile to the same SQL. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct LiveQueryKey { + role: Role, + sql: String, + params: Vec>, +} + +impl LiveQueryKey { + pub fn stable_hash(&self) -> u64 { + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + self.hash(&mut hasher); + hasher.finish() + } +} + +/// An ordinary (non-stream) table subscription compiled once before it +/// joins the server-wide polling cohort. +pub struct CompiledLiveQuery { + pub key: LiveQueryKey, + pub alias: String, + compiled: sql::CompiledRoot, +} + +pub fn compile_live_query( + pg_schema: &str, + role: Role, + operation: &ir::Operation, +) -> Option { + let [ir::RootField::Table(root)] = operation.root_fields.as_slice() else { + return None; + }; + if matches!(root.kind, ir::TableRootKind::Stream { .. }) { + return None; + } + let compiled = sql::compile_root_full(pg_schema, root); + let key = LiveQueryKey { + role, + sql: compiled.sql.clone(), + params: compiled.params.clone(), + }; + Some(CompiledLiveQuery { + key, + alias: root.alias.clone(), + compiled, + }) +} + +/// One poll for a precompiled ordinary live query. The timeout covers pool +/// admission, prepare, execution and result decoding just like HTTP work. +pub async fn poll_live_query( + state: &Arc, + live: &CompiledLiveQuery, +) -> Result { + with_query_timeout(state, sql::execute_root_compiled(state, &live.compiled)).await +} + +/// Executes `_stream` subscription polls for one subscription, compiling +/// the SQL once and re-executing it each poll with only the cursor +/// parameter values swapped in place. It recompiles only when the cursor's +/// shape changes (a column moving between unbounded / bound-at-a-value / +/// bound-at-NULL changes the predicate text), which happens at most a few +/// times over a subscription's lifetime. +#[derive(Default)] +pub struct StreamPoller { + compiled: Option, +} + +struct CompiledStream { + /// `{"data":{"alias":` — constant across polls. + prefix: String, + compiled: sql::CompiledRoot, + shape: Vec>, +} + +/// Per cursor column: `None` = unbounded, `Some(is_null)` = bounded at a +/// value / at NULL. Each shape compiles to different predicate text. +fn cursor_shape(root: &ir::TableRoot) -> Vec> { + match &root.kind { + ir::TableRootKind::Stream { cursor, .. } => cursor + .iter() + .map(|c| c.initial_value.as_ref().map(|v| v.text.is_none())) + .collect(), + _ => Vec::new(), + } +} + +impl StreamPoller { + pub fn new() -> StreamPoller { + StreamPoller::default() + } + + /// One subscription poll: returns the response body for a non-empty + /// batch (advancing the cursor past its last row, NULL cursor values + /// included), or `None` when the batch was empty. The next cursor + /// position comes back from the same query as the batch (see + /// `sql::execute_stream_compiled`) instead of a second poll-doubling + /// round trip. + pub async fn poll( + &mut self, + state: &Arc, + operation: &mut ir::Operation, + ) -> Result, GraphQLError> { + with_query_timeout(state, self.poll_inner(state, operation)).await + } + + async fn poll_inner( + &mut self, + state: &Arc, + operation: &mut ir::Operation, + ) -> Result, GraphQLError> { + let Some(ir::RootField::Table(root)) = operation.root_fields.first() else { + return Err(GraphQLError::unexpected_payload( + "internal: stream operation missing its table root field", + )); + }; + if self.compiled.is_none() { + let compiled = sql::compile_root_full(&state.model.pg_schema, root); + let mut prefix = String::with_capacity(16 + root.alias.len()); + prefix.push_str("{\"data\":{"); + prefix.push_str(&serde_json::to_string(&root.alias).unwrap()); + prefix.push(':'); + self.compiled = Some(CompiledStream { + prefix, + compiled, + shape: cursor_shape(root), + }); + } + let c = self.compiled.as_ref().unwrap(); + let mut out = String::with_capacity(c.prefix.len() + 258); + out.push_str(&c.prefix); + let cursor = + sql::execute_stream_compiled(state, &c.compiled.sql, &c.compiled.params, &mut out) + .await?; + out.push_str("}}"); + let Some(values) = cursor else { + return Ok(None); + }; + + let Some(ir::RootField::Table(root)) = operation.root_fields.first_mut() else { + unreachable!("checked above"); + }; + if let ir::TableRootKind::Stream { cursor, .. } = &mut root.kind { + update_stream_cursor_positions(cursor, &values); + } + let new_shape = cursor_shape(root); + let c = self.compiled.as_mut().unwrap(); + if new_shape == c.shape { + for &(ci, slot) in &c.compiled.cursor_slots { + c.compiled.params[slot] = values[ci].clone(); + } + } else { + self.compiled = None; + } + Ok(Some(out)) + } +} + +fn update_stream_cursor_positions(cursors: &mut [ir::StreamCursor], values: &[Option]) { + for (cursor, value) in cursors.iter_mut().zip(values) { + cursor.initial_value = Some(ir::SqlValue { + text: value.clone(), + cast: cursor.cast.clone(), + }); + } +} + +/// Runs every root field concurrently instead of one at a time, then +/// splices their fragments back in the request's original order (each +/// fragment is computed independently, so completion order doesn't matter, +/// only the order they're written to `out` in). +/// +/// A query with N table root fields can therefore hold up to N pooled +/// connections at once instead of one at a time -- the same total DB work, +/// just concurrent instead of serial. That's bounded by the existing pool +/// safety valves: `ENVIO_SERVE_POOL_MAX_SIZE` caps how many connections +/// exist at all, and `ENVIO_SERVE_POOL_WAIT_TIMEOUT_MS` turns "pool +/// exhausted" into a clean per-field error instead of an unbounded wait, so +/// a single many-root-field request can't monopolize the pool indefinitely. +async fn execute_operation_inner( + state: &Arc, + schema: &RoleSchema, + operation: &ir::Operation, +) -> Result { + let root_type_name = match operation.kind { + ir::OperationKind::Query => "query_root", + ir::OperationKind::Subscription => "subscription_root", + }; + let fragments = futures_util::future::join_all( + operation + .root_fields + .iter() + .map(|root| execute_root_field(state, schema, root_type_name, root)), + ) + .await; + + let mut out = String::with_capacity(256); + out.push_str("{\"data\":{"); + for (i, fragment) in fragments.into_iter().enumerate() { + if i > 0 { + out.push(','); + } + out.push_str(&fragment?); + } + out.push_str("}}"); + Ok(out) +} + +/// One root field's `"alias":value` fragment. +async fn execute_root_field( + state: &Arc, + schema: &RoleSchema, + root_type_name: &str, + root: &ir::RootField, +) -> Result { + match root { + ir::RootField::Typename { alias } => Ok(format!( + "{}:\"{root_type_name}\"", + serde_json::to_string(alias).unwrap() + )), + ir::RootField::Introspection(intro) => { + let value_json = introspection::resolve(&schema.registry, intro)?; + Ok(format!( + "{}:{value_json}", + serde_json::to_string(&intro.alias).unwrap() + )) + } + ir::RootField::Table(table_root) => { + let mut out = serde_json::to_string(&table_root.alias).unwrap(); + out.push(':'); + sql::execute_root(state, table_root, &mut out).await?; + Ok(out) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn live_operation(alias: &str, id: &str) -> ir::Operation { + ir::Operation { + kind: ir::OperationKind::Subscription, + root_fields: vec![ir::RootField::Table(ir::TableRoot { + alias: alias.to_string(), + table: "User".to_string(), + kind: ir::TableRootKind::ByPk { + pk: vec![("id".to_string(), ir::SqlValue::new(id, "text"))], + selection: ir::ObjectSelection { + table: "User".to_string(), + items: Vec::new(), + }, + }, + })], + } + } + + #[test] + fn live_query_cohort_key_uses_sql_params_and_role_but_not_alias() { + let public_a = compile_live_query("public", Role::Public, &live_operation("a", "1")) + .expect("ordinary table subscription"); + let public_b = compile_live_query("public", Role::Public, &live_operation("b", "1")) + .expect("ordinary table subscription"); + let different_params = + compile_live_query("public", Role::Public, &live_operation("a", "2")) + .expect("ordinary table subscription"); + let different_role = compile_live_query("public", Role::Admin, &live_operation("a", "1")) + .expect("ordinary table subscription"); + + assert_eq!(public_a.key, public_b.key); + assert_eq!(public_a.alias, "a"); + assert_eq!(public_b.alias, "b"); + assert_ne!(public_a.key, different_params.key); + assert_ne!(public_a.key, different_role.key); + } + + #[test] + fn stream_cursor_advance_preserves_array_cast() { + let mut cursors = vec![ir::StreamCursor { + column: "tags".to_string(), + cast: "text[]".to_string(), + initial_value: None, + descending: false, + }]; + update_stream_cursor_positions(&mut cursors, &[Some("{a,b}".to_string())]); + let advanced = cursors[0].initial_value.as_ref().unwrap(); + assert_eq!( + (advanced.text.as_deref(), advanced.cast.as_str()), + (Some("{a,b}"), "text[]") + ); + } +} diff --git a/packages/cli/src/serve/exec/sql.rs b/packages/cli/src/serve/exec/sql.rs new file mode 100644 index 0000000000..21b4e35cdf --- /dev/null +++ b/packages/cli/src/serve/exec/sql.rs @@ -0,0 +1,2313 @@ +//! Compiles a table root field into one SQL statement and executes it, +//! returning the raw JSON text produced by Postgres so serialization is +//! byte-identical to Hasura's. +//! +//! The SQL mirrors the shapes Hasura v2.43 generates (verified against +//! `/v1/graphql/explain` on a live instance): rows are serialized with +//! `row_to_json` over an aliased subselect, lists aggregated with +//! `json_agg`, aggregates built with `json_build_object`, relationships +//! joined via `LEFT OUTER JOIN LATERAL`. With STRINGIFY_NUMERIC_TYPES, +//! non-array bigint/numeric/float8 values (and their sum/avg/min/... +//! aggregates) are cast to `::text`; float4, arrays and everything else +//! use Postgres' native JSON serialization. + +use super::error::{GResult, GraphQLError, CODE_POSTGRES_ERROR, CODE_UNEXPECTED}; +use super::ir; +use crate::serve::ServeState; +use futures_util::TryStreamExt; +use std::fmt::Write as _; +use std::sync::Arc; +use std::time::{Duration, Instant}; +use tokio_postgres::types::{ToSql, Type}; + +/// Above this many cached prepared statements on one pooled connection the +/// whole per-connection cache is dropped. Dropping the cached `Statement` +/// handles sends a protocol-level Close for each server-side prepared +/// statement (tokio-postgres `StatementInner::drop`), so this bounds both +/// server and Postgres backend memory even under an unbounded variety of +/// query texts. +const STATEMENT_CACHE_CAP: usize = 500; + +fn slow_query_threshold() -> Duration { + static MS: std::sync::OnceLock = std::sync::OnceLock::new(); + Duration::from_millis(*MS.get_or_init(|| { + std::env::var("ENVIO_SERVE_SLOW_QUERY_MS") + .ok() + .and_then(|v| v.parse().ok()) + .unwrap_or(5000) + })) +} + +/// Stable identifier for one compiled statement, loggable without exposing +/// the full SQL text. +fn sql_hash(sql: &str) -> String { + use std::hash::{Hash, Hasher}; + let mut h = std::collections::hash_map::DefaultHasher::new(); + sql.hash(&mut h); + format!("{:016x}", h.finish()) +} + +/// Runs `sql`/`params` (as compiled by `compile_root`) and returns the +/// single output row every root-field query produces. +async fn run_root_query( + state: &Arc, + sql: &str, + params: &[Option], +) -> GResult { + let started = Instant::now(); + // Pool failures (connect refused, wait timeout) get the same + // postgres-error code as connection-level query failures so + // subscriptions can tell "Postgres is briefly unreachable" (retryable) + // apart from deterministic query errors. + let client = state.pool.get().await.map_err(|e| { + tracing::error!(error = %e, "envio serve: postgres pool checkout failed"); + GraphQLError { + message: "database query error".to_string(), + path: "$".to_string(), + code: CODE_POSTGRES_ERROR, + status: 200, + } + })?; + if client.statement_cache.size() >= STATEMENT_CACHE_CAP { + client.statement_cache.clear(); + } + // All parameters are bound as text and cast in the SQL itself + // (`($1)::numeric`), which keeps runtime coercion errors identical to + // Hasura's inlined-literal form. + let types = vec![Type::TEXT; params.len()]; + let stmt = client + .prepare_typed_cached(sql, &types) + .await + .map_err(|e| pg_error(e, sql))?; + let row_stream = client + .query_raw(&stmt, params.iter().map(|p| p as &(dyn ToSql + Sync))) + .await + .map_err(|e| pg_error(e, sql))?; + // Every compiled statement is expected to produce exactly one row, but + // read only the first one off the wire instead of buffering a Vec: a + // statement that unexpectedly degenerates to per-row output must not + // buffer the whole table in memory. + futures_util::pin_mut!(row_stream); + let row = row_stream.try_next().await.map_err(|e| pg_error(e, sql))?; + let elapsed = started.elapsed(); + if elapsed >= slow_query_threshold() { + tracing::warn!( + elapsed_ms = elapsed.as_millis() as u64, + sql_hash = %sql_hash(sql), + "envio serve: slow root-field query" + ); + } + match row { + // Hasura fails the same way when its aggregate statement degenerates + // to a non-aggregate query (e.g. `_aggregate { aggregate { __typename } }`) + // over an empty table. + None => { + tracing::warn!( + sql_hash = %sql_hash(sql), + "envio serve: root-field query returned no rows" + ); + Err(internal_db_error()) + } + Some(row) => Ok(row), + } +} + +/// Executes one table root field, appending the JSON fragment for its value +/// (e.g. `[{"id":"..."}]`, `{"aggregate":{"count":3}}`, or `null`) to `out`. +/// +/// Writes the driver's `&str` column value straight into `out` instead of +/// collecting it into an intermediate `String` first — on large unfiltered +/// list queries (tens of MB of JSON per response) that owned copy briefly +/// doubled peak memory, since Postgres already hands back one contiguous +/// text value. +pub async fn execute_root( + state: &Arc, + root: &ir::TableRoot, + out: &mut String, +) -> GResult<()> { + let compiled = compile_root_full(&state.model.pg_schema, root); + let row = run_root_query(state, &compiled.sql, &compiled.params).await?; + let text: &str = row.try_get(0).map_err(|e| { + tracing::warn!(error = %e, "envio serve: root value decode failed"); + internal_db_error() + })?; + out.push_str(text); + Ok(()) +} + +/// Executes an already-compiled ordinary live-query root and owns the +/// result so one Postgres response can be fanned out to many subscribers. +/// Compilation is deliberately outside the poll loop. +pub async fn execute_root_compiled( + state: &Arc, + compiled: &CompiledRoot, +) -> GResult { + let row = run_root_query(state, &compiled.sql, &compiled.params).await?; + let text: &str = row.try_get(0).map_err(|e| { + tracing::warn!(error = %e, "envio serve: live-query root value decode failed"); + internal_db_error() + })?; + Ok(text.to_string()) +} + +/// Like `execute_root`, but for an already-compiled `_stream` root: also +/// reads back each cursor column's value for the batch's last row from the +/// same query result (see `emit_stream_select`), instead of a second, +/// near-identical query fired just to read those columns back out -- +/// halving the DB load of each subscription poll. Returns `None` (cursor +/// unchanged) when the batch was empty. +/// +/// A non-empty batch always delivers its cursor values; individual values +/// can be `None` because NULL cursor positions are reachable (nullable +/// columns are exposed in `_stream_cursor_value_input`, and DESC +/// ordering puts NULL rows in the first batch) — the compiled predicate +/// handles a NULL position (see `emit_cursor_bounds`). +pub async fn execute_stream_compiled( + state: &Arc, + sql: &str, + params: &[Option], + out: &mut String, +) -> GResult>>> { + let row = run_root_query(state, sql, params).await?; + let root_text: &str = row.try_get(0).map_err(|e| { + tracing::warn!(error = %e, "envio serve: stream root value decode failed"); + internal_db_error() + })?; + out.push_str(root_text); + if root_text == "[]" { + return Ok(None); + } + + let mut cursor_values = Vec::with_capacity(row.len().saturating_sub(1)); + for i in 1..row.len() { + let v = row.try_get::<_, Option<&str>>(i).map_err(|e| { + tracing::warn!(error = %e, "envio serve: stream cursor value decode failed"); + internal_db_error() + })?; + cursor_values.push(v.map(str::to_string)); + } + Ok(Some(cursor_values)) +} + +fn internal_db_error() -> GraphQLError { + GraphQLError { + message: "database query error".to_string(), + path: "$".to_string(), + code: CODE_UNEXPECTED, + status: 200, + } +} + +fn pg_error(e: tokio_postgres::Error, sql: &str) -> GraphQLError { + let Some(db) = e.as_db_error() else { + tracing::warn!( + error = %e, + sql_hash = %sql_hash(sql), + "envio serve: connection-level postgres query failure" + ); + return GraphQLError { + message: "database query error".to_string(), + path: "$".to_string(), + code: CODE_POSTGRES_ERROR, + status: 200, + }; + }; + // Server-side cancellation (statement_timeout etc.) is the server twin + // of the client-side query timeout, so it gets the retryable + // postgres-error code instead of the deterministic "unexpected" mask. + if db.code().code() == "57014" { + tracing::warn!( + error = %db, + sqlstate = %db.code().code(), + sql_hash = %sql_hash(sql), + "envio serve: postgres query cancelled" + ); + return GraphQLError { + message: "database query error".to_string(), + path: "$".to_string(), + code: CODE_POSTGRES_ERROR, + status: 200, + }; + } + // Hasura maps SQLSTATE classes: data exceptions and constraint + // violations surface the Postgres message, everything else is the + // opaque "unexpected" internal error. + let class = &db.code().code()[..2.min(db.code().code().len())]; + let (code, message) = match class { + "22" => ("data-exception", db.message().to_string()), + "23" => ("constraint-violation", db.message().to_string()), + _ => { + tracing::warn!( + error = %db, + sqlstate = %db.code().code(), + sql_hash = %sql_hash(sql), + "envio serve: postgres error masked as \"database query error\"" + ); + (CODE_UNEXPECTED, "database query error".to_string()) + } + }; + GraphQLError { + message, + path: "$".to_string(), + code, + status: 200, + } +} + +#[derive(Clone)] +pub struct CompiledRoot { + pub sql: String, + pub params: Vec>, + /// Every parameter slot bound to a stream-cursor value, as + /// (cursor index, param index) — one cursor value may occupy several + /// slots (strict bound + tie equality). Lets a subscription poll loop + /// swap in the next cursor position without recompiling the SQL. + pub cursor_slots: Vec<(usize, usize)>, +} + +pub fn compile_root_full(pg_schema: &str, root: &ir::TableRoot) -> CompiledRoot { + let mut b = Sql::new(pg_schema, estimate_capacity(root)); + match &root.kind { + ir::TableRootKind::Many { args, selection } => { + let ra = RowsArgs::from_select_args(args); + emit_many_select(&mut b, &root.table, &ra, selection, None, Out::Root); + } + ir::TableRootKind::ByPk { pk, selection } => { + let ra = RowsArgs { + pk, + ..RowsArgs::default() + }; + b.push("SELECT (coalesce((json_agg(\"_v\")->0), 'null'))::text AS \"root\" FROM ("); + emit_rows_middle(&mut b, &root.table, &ra, selection, None); + b.push(") AS \"_r\""); + } + ir::TableRootKind::Aggregate { args, selection } => { + let ra = RowsArgs::from_select_args(args); + emit_agg_select(&mut b, &root.table, &ra, selection, None, Out::Root); + } + ir::TableRootKind::Stream { + batch_size, + cursor, + where_, + selection, + } => { + let ra = RowsArgs { + where_: where_.as_ref(), + cursors: cursor, + order: cursor + .iter() + .map(|c| Ord { + target: OrdTarget::Col(&c.column), + dir: if c.descending { "DESC" } else { "ASC" }, + }) + .collect(), + limit: Some(*batch_size), + ..RowsArgs::default() + }; + emit_stream_select(&mut b, &root.table, &ra, selection); + } + } + CompiledRoot { + sql: b.text, + params: b.params, + cursor_slots: b.cursor_slots, + } +} + +/// Rough output-size guess from the IR shape, so the text buffer doesn't +/// crawl up through repeated reallocation on deeply nested selections. +fn estimate_capacity(root: &ir::TableRoot) -> usize { + fn sel(s: &ir::ObjectSelection) -> usize { + s.items + .iter() + .map(|i| match i { + ir::SelItem::Typename { .. } | ir::SelItem::Column { .. } => 48, + ir::SelItem::ObjectRel { selection, .. } + | ir::SelItem::ArrayRel { selection, .. } => 280 + sel(selection), + ir::SelItem::ArrayRelAggregate { .. } => 448, + }) + .sum() + } + 256 + match &root.kind { + ir::TableRootKind::Many { selection, .. } + | ir::TableRootKind::ByPk { selection, .. } + | ir::TableRootKind::Stream { selection, .. } => sel(selection), + ir::TableRootKind::Aggregate { selection, .. } => { + selection.items.len() * 96 + + selection + .items + .iter() + .map(|i| match i { + ir::AggSelItem::Nodes { selection, .. } => sel(selection), + _ => 0, + }) + .sum::() + } + } +} + +/// Table alias `"tN"`; aliases never need quoting-escapes, so they are +/// written straight into the text buffer without an intermediate String. +#[derive(Clone, Copy)] +struct Alias(usize); + +struct Sql<'a> { + text: String, + params: Vec>, + cursor_slots: Vec<(usize, usize)>, + schema: &'a str, + aliases: usize, +} + +impl<'a> Sql<'a> { + fn new(schema: &'a str, capacity: usize) -> Sql<'a> { + Sql { + text: String::with_capacity(capacity), + params: Vec::new(), + cursor_slots: Vec::new(), + schema, + aliases: 0, + } + } + + fn alias(&mut self) -> Alias { + let a = Alias(self.aliases); + self.aliases += 1; + a + } + + fn push(&mut self, s: &str) { + self.text.push_str(s); + } + + fn push_alias(&mut self, a: Alias) { + let _ = write!(self.text, "\"t{}\"", a.0); + } + + /// `"prefixK"` for the fixed internal column names (`_oK`, `_pcK`, ...). + fn ident_n(&mut self, prefix: &str, k: usize) { + let _ = write!(self.text, "\"{prefix}{k}\""); + } + + fn ident(&mut self, name: &str) { + push_ident_to(&mut self.text, name); + } + + fn string_lit(&mut self, s: &str) { + self.text.push('\''); + for c in s.chars() { + if c == '\'' { + self.text.push('\''); + } + self.text.push(c); + } + self.text.push('\''); + } + + fn qual(&mut self, alias: Alias, col: &str) { + self.push_alias(alias); + self.text.push('.'); + self.ident(col); + } + + fn table(&mut self, name: &str) { + let schema = self.schema; + self.text.push('"'); + self.text.push_str(schema); + self.text.push_str("\"."); + self.ident(name); + } + + /// `::cast`, quoting the base type name unless it is a plain lowercase + /// name (builtin types, and enum types created unquoted). + fn push_cast(&mut self, cast: &str) { + self.text.push_str("::"); + let base = cast.trim_end_matches("[]"); + // Custom casts are pre-quoted as `"schema"."type"` by the + // coercion layer using catalog-owned identifiers. Keep that safe, + // qualified form intact instead of quoting it as one identifier. + if base.starts_with('"') { + self.text.push_str(cast); + return; + } + let plain = !base.is_empty() + && base + .chars() + .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == ' '); + if plain { + self.text.push_str(cast); + } else { + let brackets = cast.len() - base.len(); + let base = base.to_string(); + self.ident(&base); + self.text.push_str(&cast[cast.len() - brackets..]); + } + } + + /// `(($n)::cast)` binding one value; returns the param slot index. + fn param_text(&mut self, text: Option, cast: &str) -> usize { + self.params.push(text); + let n = self.params.len(); + let _ = write!(self.text, "((${n})"); + self.push_cast(cast); + self.text.push(')'); + n - 1 + } + + fn param(&mut self, v: &ir::SqlValue) -> usize { + self.param_text(v.text.clone(), &v.cast) + } + + fn param_i64(&mut self, v: i64) { + self.param_text(Some(v.to_string()), "int8"); + } + + /// `(($n)::elem_cast[])` binding one array-literal parameter built from + /// the elements' text forms. + fn param_array<'i>(&mut self, elems: impl Iterator>, elem_cast: &str) { + let mut lit = String::from("{"); + for (i, e) in elems.enumerate() { + if i > 0 { + lit.push(','); + } + match e { + None => lit.push_str("NULL"), + Some(s) => { + lit.push('"'); + for c in s.chars() { + if c == '"' || c == '\\' { + lit.push('\\'); + } + lit.push(c); + } + lit.push('"'); + } + } + } + lit.push('}'); + self.param_text(Some(lit), &format!("{elem_cast}[]")); + } +} + +fn dir_sql(d: ir::OrderDirection) -> &'static str { + match d { + ir::OrderDirection::Asc | ir::OrderDirection::AscNullsLast => "ASC NULLS LAST", + ir::OrderDirection::AscNullsFirst => "ASC NULLS FIRST", + ir::OrderDirection::Desc | ir::OrderDirection::DescNullsFirst => "DESC NULLS FIRST", + ir::OrderDirection::DescNullsLast => "DESC NULLS LAST", + } +} + +enum OrdTarget<'a> { + Col(&'a str), + Rel(&'a ir::OrderTarget), +} + +struct Ord<'a> { + target: OrdTarget<'a>, + dir: &'static str, +} + +/// Join condition of a lateral/EXISTS child against its parent row: +/// `(("child"."child_col") = ("parent"."parent_col"))`. +struct Corr<'a> { + parent_alias: Alias, + parent_col: &'a str, + child_col: &'a str, +} + +#[derive(Default)] +struct RowsArgs<'a> { + pk: &'a [(String, ir::SqlValue)], + where_: Option<&'a ir::BoolExp>, + cursors: &'a [ir::StreamCursor], + order: Vec>, + distinct_on: &'a [String], + limit: Option, + offset: Option, +} + +impl<'a> RowsArgs<'a> { + fn from_select_args(args: &'a ir::SelectArgs) -> RowsArgs<'a> { + RowsArgs { + pk: &[], + where_: args.where_.as_ref(), + cursors: &[], + order: args + .order_by + .iter() + .map(|o| Ord { + target: match &o.target { + ir::OrderTarget::Column { column } => OrdTarget::Col(column), + other => OrdTarget::Rel(other), + }, + dir: dir_sql(o.direction), + }) + .collect(), + distinct_on: &args.distinct_on, + limit: args.limit, + offset: args.offset, + } + } + + /// Relationship-based order targets can only be computed alongside the + /// lateral joins, so ordering/distinct/limit move from the base table + /// subquery to the row-building level — exactly as Hasura does. + fn order_in_base(&self) -> bool { + !self + .order + .iter() + .any(|o| matches!(o.target, OrdTarget::Rel(_))) + } +} + +enum Out { + /// Root statement: the single output column is cast to text. + Root, + /// A lateral join's value column, kept as json. + Lateral, +} + +/// `SELECT coalesce(json_agg("_v" ORDER BY ...), '[]') ... FROM (rows) AS "_r"` +fn emit_many_select( + b: &mut Sql, + table: &str, + ra: &RowsArgs, + sel: &ir::ObjectSelection, + corr: Option<&Corr>, + out: Out, +) { + b.push("SELECT "); + if matches!(out, Out::Root) { + b.push("("); + } + b.push("coalesce(json_agg(\"_v\""); + emit_order_by_refs(b, &ra.order); + b.push("), '[]')"); + match out { + Out::Root => b.push(")::text AS \"root\""), + Out::Lateral => b.push(" AS \"_v\""), + } + b.push(" FROM ("); + emit_rows_middle(b, table, ra, sel, corr); + b.push(") AS \"_r\""); +} + +/// Like `emit_many_select`'s `Out::Root` shape, but also selects each order +/// (cursor) column's value from the batch's last row in final sort order, +/// text-cast for lossless round-tripping -- so a `_stream` subscription's +/// poll loop can read the next cursor position out of this same query +/// instead of firing a second, near-identical query just for that. +fn emit_stream_select(b: &mut Sql, table: &str, ra: &RowsArgs, sel: &ir::ObjectSelection) { + b.push("SELECT (coalesce(json_agg(\"_v\""); + emit_order_by_refs(b, &ra.order); + b.push("), '[]'))::text AS \"root\""); + for k in 0..ra.order.len() { + b.push(", (array_agg(("); + b.ident_n("_o", k); + b.push(")::text"); + emit_order_by_refs(b, &ra.order); + b.push("))[count(*)] AS "); + b.ident_n("cursor_", k); + } + b.push(" FROM ("); + emit_rows_middle(b, table, ra, sel, None); + b.push(") AS \"_r\""); +} + +fn emit_order_by_refs(b: &mut Sql, order: &[Ord]) { + for (k, o) in order.iter().enumerate() { + b.push(if k == 0 { " ORDER BY " } else { ", " }); + b.ident_n("_o", k); + b.push(" "); + b.push(o.dir); + } +} + +/// The row-building level: one output row per selected table row, with the +/// row JSON as "_v" and each order expression as "_oK". +fn emit_rows_middle( + b: &mut Sql, + table: &str, + ra: &RowsArgs, + sel: &ir::ObjectSelection, + corr: Option<&Corr>, +) { + let order_in_base = ra.order_in_base(); + let t = b.alias(); + let rel_aliases = alloc_rel_aliases(b, sel); + let order_join_aliases = alloc_order_join_aliases(b, &ra.order); + + b.push("SELECT "); + if !order_in_base && !ra.distinct_on.is_empty() { + emit_middle_distinct(b, ra.distinct_on.len()); + } + emit_row_json(b, t, sel, &rel_aliases); + b.push(" AS \"_v\""); + emit_order_cols(b, t, &ra.order, &order_join_aliases); + b.push(" FROM "); + emit_base(b, table, t, ra, corr, order_in_base); + emit_order_rel_joins(b, t, &ra.order, &order_join_aliases); + emit_rel_laterals(b, t, sel, &rel_aliases); + if !order_in_base { + emit_middle_order_limit(b, ra); + } +} + +fn emit_middle_distinct(b: &mut Sql, n_cols: usize) { + b.push("DISTINCT ON ("); + for k in 0..n_cols { + if k > 0 { + b.push(", "); + } + b.ident_n("_o", k); + } + b.push(") "); +} + +/// Pre-allocates one alias per hop of every `ObjectRelColumn` order target, +/// so the order column (in the SELECT list, emitted before the FROM clause +/// text) can reference the leaf alias that `emit_order_rel_joins` later +/// joins into the FROM clause — the same alloc-then-reference pattern +/// `alloc_rel_aliases`/`emit_rel_laterals` use for relationship fields. +fn alloc_order_join_aliases(b: &mut Sql, order: &[Ord]) -> Vec>> { + order + .iter() + .map(|o| match &o.target { + OrdTarget::Rel(ir::OrderTarget::ObjectRelColumn { path, .. }) => { + Some(path.iter().map(|_| b.alias()).collect()) + } + _ => None, + }) + .collect() +} + +/// The expression one order target sorts by, shared between the `_oK` +/// select-list columns and the row-number window in `emit_agg_middle`. +fn emit_order_target(b: &mut Sql, t: Alias, o: &Ord, join_aliases: &Option>) { + match (&o.target, join_aliases) { + (OrdTarget::Col(c), _) => b.qual(t, c), + (OrdTarget::Rel(ir::OrderTarget::ObjectRelColumn { column, .. }), Some(aliases)) => { + // `aliases` has one entry per path hop, and ObjectRelColumn's + // path is never empty (see validate.rs's chain-based builder). + b.qual(*aliases.last().unwrap(), column); + } + (OrdTarget::Rel(target), _) => emit_order_rel_expr(b, t, target), + } +} + +fn emit_order_cols( + b: &mut Sql, + t: Alias, + order: &[Ord], + order_join_aliases: &[Option>], +) { + for (k, o) in order.iter().enumerate() { + b.push(", "); + emit_order_target(b, t, o, &order_join_aliases[k]); + b.push(" AS "); + b.ident_n("_o", k); + } +} + +/// LEFT JOINs the tables reached by `ObjectRelColumn` order targets into the +/// FROM clause instead of computing them via a correlated subselect per row. +/// Safe because object relationships match at most one remote row (the join +/// is on the remote table's PK), so this can't change the base row count — +/// unlike a join on an array relationship, which would fan out rows. +fn emit_order_rel_joins( + b: &mut Sql, + t: Alias, + order: &[Ord], + order_join_aliases: &[Option>], +) { + for (o, aliases) in order.iter().zip(order_join_aliases) { + let (OrdTarget::Rel(ir::OrderTarget::ObjectRelColumn { path, .. }), Some(aliases)) = + (&o.target, aliases) + else { + continue; + }; + let mut parent = t; + for ((local, remote), alias) in path.iter().zip(aliases) { + b.push(" LEFT JOIN "); + b.table(remote); + b.push(" AS "); + b.push_alias(*alias); + b.push(" ON (("); + b.qual(parent, local); + b.push(") = ("); + b.qual(*alias, "id"); + b.push("))"); + parent = *alias; + } + } +} + +fn emit_middle_order_limit(b: &mut Sql, ra: &RowsArgs) { + emit_order_by_refs(b, &ra.order); + if let Some(l) = ra.limit { + b.push(" LIMIT "); + b.param_i64(l); + } + if let Some(o) = ra.offset { + b.push(" OFFSET "); + b.param_i64(o); + } +} + +/// `(SELECT [DISTINCT ON (..)] * FROM "schema"."T" AS "t" WHERE .. +/// [ORDER BY .. LIMIT .. OFFSET ..]) AS "t"` +fn emit_base( + b: &mut Sql, + table: &str, + t: Alias, + ra: &RowsArgs, + corr: Option<&Corr>, + order_in_base: bool, +) { + b.push("(SELECT "); + if order_in_base && !ra.distinct_on.is_empty() { + b.push("DISTINCT ON ("); + for (i, c) in ra.distinct_on.iter().enumerate() { + if i > 0 { + b.push(", "); + } + b.ident(c); + } + b.push(") "); + } + b.push("* FROM "); + b.table(table); + b.push(" AS "); + b.push_alias(t); + b.push(" WHERE "); + + let mut first = true; + let mut sep = |b: &mut Sql| { + if !first { + b.push(" AND "); + } + first = false; + }; + if let Some(c) = corr { + sep(b); + b.push("(("); + b.qual(t, c.child_col); + b.push(") = ("); + b.qual(c.parent_alias, c.parent_col); + b.push("))"); + } + for (col, v) in ra.pk { + sep(b); + b.push("(("); + b.qual(t, col); + b.push(") = "); + b.param(v); + b.push(")"); + } + if ra.cursors.iter().any(|c| c.initial_value.is_some()) { + sep(b); + emit_cursor_bounds(b, t, ra.cursors); + } + if let Some(w) = ra.where_ { + sep(b); + emit_bool(b, t, w); + } + if first { + b.push("('true')"); + } + + if order_in_base { + for (k, o) in ra.order.iter().enumerate() { + b.push(if k == 0 { " ORDER BY " } else { ", " }); + match &o.target { + OrdTarget::Col(c) => b.ident(c), + OrdTarget::Rel(_) => unreachable!("rel order targets are never base-ordered"), + } + b.push(" "); + b.push(o.dir); + } + if let Some(l) = ra.limit { + b.push(" LIMIT "); + b.param_i64(l); + } + if let Some(o) = ra.offset { + b.push(" OFFSET "); + b.param_i64(o); + } + } + b.push(") AS "); + b.push_alias(t); +} + +/// Lexicographic bound over the stream cursor columns; a missing initial +/// value means that column is unbounded. +/// +/// A present-but-NULL cursor value is a real bound, not an omitted one. +/// Hasura applies the same strict SQL comparison as for non-NULL values; +/// comparison with NULL cannot be true, so that cursor branch matches no +/// rows. Earlier non-NULL columns in a multi-column cursor may still advance +/// through their strict branch. +fn emit_cursor_bounds(b: &mut Sql, t: Alias, cursors: &[ir::StreamCursor]) { + let bounded: Vec<(usize, &ir::StreamCursor)> = cursors + .iter() + .enumerate() + .filter(|(_, c)| c.initial_value.is_some()) + .collect(); + + fn strict(b: &mut Sql, t: Alias, ci: usize, c: &ir::StreamCursor) { + let v = c.initial_value.as_ref().unwrap(); + match &v.text { + None => b.push("('false')"), + Some(_) => { + b.push("(("); + b.qual(t, &c.column); + b.push(")"); + b.push(if c.descending { " < " } else { " > " }); + let slot = b.param(v); + b.cursor_slots.push((ci, slot)); + b.push(")"); + } + } + } + + fn tie(b: &mut Sql, t: Alias, ci: usize, c: &ir::StreamCursor) { + let v = c.initial_value.as_ref().unwrap(); + match &v.text { + None => b.push("('false')"), + Some(_) => { + b.push("(("); + b.qual(t, &c.column); + b.push(") = "); + let slot = b.param(v); + b.cursor_slots.push((ci, slot)); + b.push(")"); + } + } + } + + fn emit_from(b: &mut Sql, t: Alias, bounded: &[(usize, &ir::StreamCursor)]) { + let (ci, c) = bounded[0]; + if c.initial_value + .as_ref() + .is_some_and(|value| value.text.is_none()) + { + b.push("('false')"); + return; + } + if bounded.len() == 1 { + strict(b, t, ci, c); + return; + } + b.push("("); + strict(b, t, ci, c); + b.push(" OR ("); + tie(b, t, ci, c); + b.push(" AND "); + emit_from(b, t, &bounded[1..]); + b.push("))"); + } + emit_from(b, t, &bounded); +} + +fn alloc_rel_aliases(b: &mut Sql, sel: &ir::ObjectSelection) -> Vec> { + sel.items + .iter() + .map(|item| match item { + ir::SelItem::ObjectRel { .. } + | ir::SelItem::ArrayRel { .. } + | ir::SelItem::ArrayRelAggregate { .. } => Some(b.alias()), + _ => None, + }) + .collect() +} + +/// `row_to_json((SELECT "_e" FROM (SELECT ) AS "_e"))` +fn emit_row_json(b: &mut Sql, t: Alias, sel: &ir::ObjectSelection, rel_aliases: &[Option]) { + if sel.items.is_empty() { + b.push("'{}'::json"); + return; + } + b.push("row_to_json((SELECT \"_e\" FROM (SELECT "); + for (i, item) in sel.items.iter().enumerate() { + if i > 0 { + b.push(", "); + } + match item { + ir::SelItem::Typename { alias, type_name } => { + b.string_lit(type_name); + b.push(" AS "); + b.ident(alias); + } + ir::SelItem::Column { + alias, + column, + scalar, + is_array, + json_path, + .. + } => { + if let Some(path) = json_path { + b.push("("); + b.qual(t, column); + b.push("#>"); + b.param_array(path.iter().map(|p| Some(p.as_str())), "text"); + b.push(")"); + } else if scalar.stringified() && !is_array { + b.push("("); + b.qual(t, column); + b.push(")::text"); + } else { + b.qual(t, column); + } + b.push(" AS "); + b.ident(alias); + } + ir::SelItem::ObjectRel { alias, .. } + | ir::SelItem::ArrayRel { alias, .. } + | ir::SelItem::ArrayRelAggregate { alias, .. } => { + let rel = rel_aliases[i].unwrap(); + b.qual(rel, "_v"); + b.push(" AS "); + b.ident(alias); + } + } + } + b.push(") AS \"_e\"))"); +} + +fn emit_rel_laterals( + b: &mut Sql, + t: Alias, + sel: &ir::ObjectSelection, + rel_aliases: &[Option], +) { + for (i, item) in sel.items.iter().enumerate() { + let Some(rel) = rel_aliases[i] else { + continue; + }; + b.push(" LEFT OUTER JOIN LATERAL ("); + match item { + ir::SelItem::ObjectRel { + local_column, + remote_table, + selection, + .. + } => { + let corr = Corr { + parent_alias: t, + parent_col: local_column, + child_col: "id", + }; + let ra = RowsArgs { + limit: Some(1), + ..RowsArgs::default() + }; + emit_rows_middle(b, remote_table, &ra, selection, Some(&corr)); + } + ir::SelItem::ArrayRel { + remote_column, + remote_table, + args, + selection, + .. + } => { + let corr = Corr { + parent_alias: t, + parent_col: "id", + child_col: remote_column, + }; + let ra = RowsArgs::from_select_args(args); + emit_many_select(b, remote_table, &ra, selection, Some(&corr), Out::Lateral); + } + ir::SelItem::ArrayRelAggregate { + remote_column, + remote_table, + args, + selection, + .. + } => { + let corr = Corr { + parent_alias: t, + parent_col: "id", + child_col: remote_column, + }; + let ra = RowsArgs::from_select_args(args); + emit_agg_select(b, remote_table, &ra, selection, Some(&corr), Out::Lateral); + } + _ => unreachable!(), + } + b.push(") AS "); + b.push_alias(rel); + b.push(" ON ('true')"); + } +} + +/// `SELECT json_build_object(..aggregates.., 'nodes', json_agg(..)) FROM +/// (SELECT , , FROM base ..) AS "_r"` +fn emit_agg_select( + b: &mut Sql, + table: &str, + ra: &RowsArgs, + sel: &ir::AggregateSelection, + corr: Option<&Corr>, + out: Out, +) { + // Columns referenced by count/op aggregates, deduplicated; each becomes + // a middle-level column "_pcK". + let add = |cols: &mut Vec, c: &str| { + if !cols.iter().any(|x| x == c) { + cols.push(c.to_string()); + } + }; + let mut cols: Vec = Vec::new(); + let mut nodes: Vec<&ir::ObjectSelection> = Vec::new(); + for item in &sel.items { + match item { + ir::AggSelItem::Aggregate { items, .. } => { + for f in items { + match f { + ir::AggFieldItem::Count { columns, .. } => { + for c in columns { + add(&mut cols, c); + } + } + ir::AggFieldItem::Op { columns, .. } => { + for c in columns { + if let ir::AggOpColumn::Column { column, .. } = c { + add(&mut cols, column); + } + } + } + ir::AggFieldItem::Typename { .. } => {} + } + } + } + ir::AggSelItem::Nodes { selection, .. } => nodes.push(selection), + ir::AggSelItem::Typename { .. } => {} + } + } + // Whether the statement contains at least one SQL aggregate function + // (count/sum/json_agg/the top-level Typename's bool_or). Without one, + // the "aggregate" degenerates to a plain per-row select whose output is + // the same constant for every table row — see the LIMIT 1 below. + let has_aggregate_fn = sel.items.iter().any(|item| match item { + ir::AggSelItem::Typename { .. } => true, + ir::AggSelItem::Nodes { .. } => true, + ir::AggSelItem::Aggregate { items, .. } => items.iter().any(|f| match f { + ir::AggFieldItem::Typename { .. } => false, + ir::AggFieldItem::Count { .. } => true, + ir::AggFieldItem::Op { columns, .. } => columns + .iter() + .any(|c| matches!(c, ir::AggOpColumn::Column { .. })), + }), + }); + let col_idx = |c: &str| -> usize { cols.iter().position(|x| x == c).unwrap() }; + + b.push("SELECT "); + if matches!(out, Out::Root) { + b.push("("); + } + b.push("json_build_object("); + let mut node_idx = 0usize; + for (i, item) in sel.items.iter().enumerate() { + if i > 0 { + b.push(", "); + } + match item { + ir::AggSelItem::Typename { alias, type_name } => { + b.string_lit(alias); + // bool_or forces aggregate context so the statement returns + // exactly one row even without other aggregate functions. + b.push(", coalesce("); + b.string_lit(type_name); + b.push(", (bool_or('true'))::text)"); + } + ir::AggSelItem::Aggregate { alias, items } => { + b.string_lit(alias); + b.push(", json_build_object("); + for (j, f) in items.iter().enumerate() { + if j > 0 { + b.push(", "); + } + emit_agg_field(b, f, &col_idx); + } + b.push(")"); + } + ir::AggSelItem::Nodes { alias, .. } => { + b.string_lit(alias); + b.push(", coalesce(json_agg("); + b.ident_n("_n", node_idx); + node_idx += 1; + emit_order_by_refs(b, &ra.order); + b.push(")"); + // The role's response limit caps nodes rows while the + // aggregates above stay uncapped. + if let Some(n) = sel.nodes_limit { + let _ = write!(b.text, " FILTER (WHERE \"_rn\" <= {n})"); + } + b.push(", '[]')"); + } + } + } + b.push(")"); + match out { + Out::Root => b.push(")::text AS \"root\""), + Out::Lateral => b.push(" AS \"_v\""), + } + b.push(" FROM ("); + let with_row_numbers = sel.nodes_limit.is_some() && !nodes.is_empty(); + emit_agg_middle(b, table, ra, &cols, &nodes, corr, with_row_numbers); + b.push(") AS \"_r\""); + if !has_aggregate_fn { + // Every output row is the same constant, so cap the scan at one row + // instead of materializing one per table row. Zero rows on an empty + // table still surface Hasura's "database query error" (see + // `run_root_query`). + b.push(" LIMIT 1"); + } +} + +fn emit_agg_field(b: &mut Sql, f: &ir::AggFieldItem, col_idx: &dyn Fn(&str) -> usize) { + match f { + ir::AggFieldItem::Typename { alias, type_name } => { + b.string_lit(alias); + b.push(", "); + b.string_lit(type_name); + } + ir::AggFieldItem::Count { + alias, + columns, + distinct, + } => { + b.string_lit(alias); + b.push(", count("); + if columns.is_empty() { + b.push("*"); + } else { + if *distinct { + b.push("DISTINCT "); + } + b.push("("); + for (i, c) in columns.iter().enumerate() { + if i > 0 { + b.push(", "); + } + b.push("\"_r\"."); + b.ident_n("_pc", col_idx(c)); + } + b.push(")"); + } + b.push(")"); + } + ir::AggFieldItem::Op { alias, columns, .. } => { + b.string_lit(alias); + b.push(", json_build_object("); + for (i, c) in columns.iter().enumerate() { + if i > 0 { + b.push(", "); + } + match c { + ir::AggOpColumn::Typename { alias, type_name } => { + b.string_lit(alias); + b.push(", "); + b.string_lit(type_name); + } + ir::AggOpColumn::Column { + alias, + column, + scalar, + is_array, + op, + .. + } => { + b.string_lit(alias); + b.push(", "); + let stringify = scalar.stringified() && !is_array; + if stringify { + b.push("("); + } + b.push(op); + b.push("("); + b.push("\"_r\"."); + b.ident_n("_pc", col_idx(column)); + b.push(")"); + if stringify { + b.push(")::text"); + } + } + } + } + b.push(")"); + } + } +} + +fn emit_agg_middle( + b: &mut Sql, + table: &str, + ra: &RowsArgs, + cols: &[String], + nodes: &[&ir::ObjectSelection], + corr: Option<&Corr>, + with_row_numbers: bool, +) { + let order_in_base = ra.order_in_base(); + // Relationship order targets are resolved at this middle level, so its + // OFFSET/LIMIT/DISTINCT clauses run after window functions. Number the + // already-paginated rows in one extra layer; otherwise `_rn <= n` + // applies the public nodes cap to pre-offset row numbers and can return + // fewer than n nodes (or none at all). + if with_row_numbers && !order_in_base { + b.push("SELECT \"_p\".*, row_number() OVER ("); + emit_order_by_refs(b, &ra.order); + b.push(") AS \"_rn\" FROM ("); + emit_agg_middle_rows(b, table, ra, cols, nodes, corr, false, order_in_base); + b.push(") AS \"_p\""); + return; + } + emit_agg_middle_rows( + b, + table, + ra, + cols, + nodes, + corr, + with_row_numbers, + order_in_base, + ); +} + +#[allow(clippy::too_many_arguments)] +fn emit_agg_middle_rows( + b: &mut Sql, + table: &str, + ra: &RowsArgs, + cols: &[String], + nodes: &[&ir::ObjectSelection], + corr: Option<&Corr>, + with_row_numbers: bool, + order_in_base: bool, +) { + let t = b.alias(); + let node_rel_aliases: Vec>> = + nodes.iter().map(|sel| alloc_rel_aliases(b, sel)).collect(); + let order_join_aliases = alloc_order_join_aliases(b, &ra.order); + + b.push("SELECT "); + if !order_in_base && !ra.distinct_on.is_empty() { + emit_middle_distinct(b, ra.distinct_on.len()); + } + let mut first = true; + for (k, c) in cols.iter().enumerate() { + if !first { + b.push(", "); + } + first = false; + b.qual(t, c); + b.push(" AS "); + b.ident_n("_pc", k); + } + for (n, sel) in nodes.iter().enumerate() { + if !first { + b.push(", "); + } + first = false; + emit_row_json(b, t, sel, &node_rel_aliases[n]); + b.push(" AS "); + b.ident_n("_n", n); + } + if with_row_numbers { + if !first { + b.push(", "); + } + first = false; + // The requested ORDER BY goes inside the window: an empty OVER () + // numbers rows in scan order, which need not match the ordering + // applied above the base relation, so the `_rn <= n` FILTER would + // keep arbitrary rows instead of the first n in requested order. + b.push("row_number() OVER ("); + for (k, o) in ra.order.iter().enumerate() { + b.push(if k == 0 { "ORDER BY " } else { ", " }); + emit_order_target(b, t, o, &order_join_aliases[k]); + b.push(" "); + b.push(o.dir); + } + b.push(") AS \"_rn\""); + } + if first && ra.order.is_empty() { + b.push("1"); + } else if first && !ra.order.is_empty() { + // Order columns follow with a leading comma; keep the list valid. + b.push("1 AS \"_one\""); + } + emit_order_cols(b, t, &ra.order, &order_join_aliases); + b.push(" FROM "); + emit_base(b, table, t, ra, corr, order_in_base); + emit_order_rel_joins(b, t, &ra.order, &order_join_aliases); + for (n, sel) in nodes.iter().enumerate() { + emit_rel_laterals(b, t, sel, &node_rel_aliases[n]); + } + if !order_in_base { + emit_middle_order_limit(b, ra); + } +} + +/// Order expression for an `ArrayRelAggregate` target, as a correlated +/// subselect (`ObjectRelColumn` targets are LEFT JOINed in by +/// `emit_order_rel_joins` instead; `Column` never reaches here — see +/// `RowsArgs::from_select_args`). +fn emit_order_rel_expr(b: &mut Sql, parent: Alias, target: &ir::OrderTarget) { + match target { + ir::OrderTarget::Column { .. } | ir::OrderTarget::ObjectRelColumn { .. } => { + unreachable!("handled directly in emit_order_target") + } + ir::OrderTarget::ArrayRelAggregate { + path, + remote_column, + remote_table, + op, + column, + } => { + emit_order_obj_path(b, parent, path, &mut |b, leaf| { + let a = b.alias(); + b.push("(SELECT "); + if op == "count" && column.is_none() { + b.push("count(*)"); + } else { + b.push(op); + b.push("("); + if let Some(c) = column { + b.qual(a, c); + } else { + b.push("*"); + } + b.push(")"); + } + b.push(" FROM "); + b.table(remote_table); + b.push(" AS "); + b.push_alias(a); + b.push(" WHERE (("); + b.qual(a, remote_column); + b.push(") = ("); + b.qual(leaf, "id"); + b.push(")))"); + }); + } + } +} + +/// Walks object-relationship hops `(local col, remote table)` and calls +/// `leaf` with the alias of the innermost table. +fn emit_order_obj_path( + b: &mut Sql, + parent: Alias, + path: &[(String, String)], + leaf: &mut dyn FnMut(&mut Sql, Alias), +) { + match path.split_first() { + None => leaf(b, parent), + Some(((local, remote), rest)) => { + let a = b.alias(); + b.push("(SELECT "); + emit_order_obj_path(b, a, rest, leaf); + b.push(" FROM "); + b.table(remote); + b.push(" AS "); + b.push_alias(a); + b.push(" WHERE (("); + b.qual(parent, local); + b.push(") = ("); + b.qual(a, "id"); + b.push(")) LIMIT 1)"); + } + } +} + +fn emit_bool(b: &mut Sql, t: Alias, e: &ir::BoolExp) { + match e { + ir::BoolExp::And(list) => { + if list.is_empty() { + b.push("('true')"); + } else { + b.push("("); + for (i, e) in list.iter().enumerate() { + if i > 0 { + b.push(" AND "); + } + emit_bool(b, t, e); + } + b.push(")"); + } + } + ir::BoolExp::Or(list) => { + if list.is_empty() { + b.push("('false')"); + } else { + b.push("("); + for (i, e) in list.iter().enumerate() { + if i > 0 { + b.push(" OR "); + } + emit_bool(b, t, e); + } + b.push(")"); + } + } + ir::BoolExp::Not(e) => { + b.push("(NOT "); + emit_bool(b, t, e); + b.push(")"); + } + ir::BoolExp::Compare { + column, + pg_type, + op, + .. + } => { + let mut lhs = String::new(); + lhs_qual(&mut lhs, t, column); + emit_compare(b, &lhs, op, pg_type); + } + ir::BoolExp::ObjectRel { + local_column, + remote_table, + exp, + } => { + emit_exists(b, remote_table, "id", t, local_column, exp); + } + ir::BoolExp::ArrayRel { + remote_column, + remote_table, + exp, + } => { + emit_exists(b, remote_table, remote_column, t, "id", exp); + } + ir::BoolExp::ArrayRelAggregate { + remote_column, + remote_table, + pred, + } => { + let a = b.alias(); + b.push("(EXISTS (SELECT 1 FROM (SELECT "); + emit_agg_predicate_expr(b, a, pred); + b.push(" AS \"_agg\" FROM "); + b.table(remote_table); + b.push(" AS "); + b.push_alias(a); + b.push(" WHERE ((("); + b.qual(a, remote_column); + b.push(") = ("); + b.qual(t, "id"); + b.push("))"); + if let Some(f) = &pred.filter { + b.push(" AND "); + emit_bool(b, a, f); + } + b.push(")) AS \"_sub\" WHERE "); + if pred.predicate.is_empty() { + b.push("('true')"); + } else { + let result_type = if pred.op == "count" { "int4" } else { "bool" }; + b.push("("); + for (i, op) in pred.predicate.iter().enumerate() { + if i > 0 { + b.push(" AND "); + } + emit_compare(b, "(\"_sub\".\"_agg\")", op, result_type); + } + b.push(")"); + } + b.push("))"); + } + } +} + +fn emit_exists( + b: &mut Sql, + remote_table: &str, + child_col: &str, + parent: Alias, + parent_col: &str, + exp: &ir::BoolExp, +) { + let a = b.alias(); + b.push("(EXISTS (SELECT 1 FROM "); + b.table(remote_table); + b.push(" AS "); + b.push_alias(a); + b.push(" WHERE ((("); + b.qual(a, child_col); + b.push(") = ("); + b.qual(parent, parent_col); + b.push(")) AND "); + emit_bool(b, a, exp); + b.push(")))"); +} + +fn emit_agg_predicate_expr(b: &mut Sql, t: Alias, pred: &ir::AggregatePredicate) { + if pred.op == "count" && pred.columns.is_empty() { + b.push("count(*)"); + return; + } + b.push(&pred.op); + b.push("("); + if pred.distinct { + b.push("DISTINCT "); + } + if pred.columns.is_empty() { + b.push("*"); + } else { + for (i, c) in pred.columns.iter().enumerate() { + if i > 0 { + b.push(", "); + } + b.qual(t, c); + } + } + b.push(")"); +} + +fn lhs_qual(out: &mut String, alias: Alias, col: &str) { + let _ = write!(out, "(\"t{}\".", alias.0); + push_ident_to(out, col); + out.push(')'); +} + +fn push_ident_to(out: &mut String, name: &str) { + out.push('"'); + for c in name.chars() { + if c == '"' { + out.push('"'); + } + out.push(c); + } + out.push('"'); +} + +fn emit_compare(b: &mut Sql, lhs: &str, op: &ir::CompareOp, pg_type: &str) { + use ir::CompareOp as C; + + let binary = |b: &mut Sql, sql_op: &str, v: &ir::SqlValue| { + b.push("("); + b.push(lhs); + b.push(" "); + b.push(sql_op); + b.push(" "); + b.param(v); + b.push(")"); + }; + + match op { + C::Eq(v) => binary(b, "=", v), + C::Neq(v) => binary(b, "<>", v), + C::Gt(v) => binary(b, ">", v), + C::Gte(v) => binary(b, ">=", v), + C::Lt(v) => binary(b, "<", v), + C::Lte(v) => binary(b, "<=", v), + C::Like(v) => binary(b, "LIKE", v), + C::Nlike(v) => binary(b, "NOT LIKE", v), + C::Ilike(v) => binary(b, "ILIKE", v), + C::Nilike(v) => binary(b, "NOT ILIKE", v), + C::Similar(v) => binary(b, "SIMILAR TO", v), + C::Nsimilar(v) => binary(b, "NOT SIMILAR TO", v), + C::Regex(v) => binary(b, "~", v), + C::Iregex(v) => binary(b, "~*", v), + C::Nregex(v) => binary(b, "!~", v), + C::Niregex(v) => binary(b, "!~*", v), + C::Contains(v) => binary(b, "@>", v), + C::ContainedIn(v) => binary(b, "<@", v), + C::HasKey(v) => binary(b, "?", v), + C::In(vs) => { + b.push("("); + b.push(lhs); + b.push(" = ANY("); + emit_in_array(b, vs, pg_type); + b.push("))"); + } + C::Nin(vs) => { + b.push("(NOT ("); + b.push(lhs); + b.push(" = ANY("); + emit_in_array(b, vs, pg_type); + b.push(")))"); + } + C::IsNull(true) => { + b.push("("); + b.push(lhs); + b.push(" IS NULL)"); + } + C::IsNull(false) => { + b.push("("); + b.push(lhs); + b.push(" IS NOT NULL)"); + } + C::HasKeysAll(vs) => { + b.push("("); + b.push(lhs); + b.push(" ?& "); + b.param_array(vs.iter().map(|v| v.text.as_deref()), "text"); + b.push(")"); + } + C::HasKeysAny(vs) => { + b.push("("); + b.push(lhs); + b.push(" ?| "); + b.param_array(vs.iter().map(|v| v.text.as_deref()), "text"); + b.push(")"); + } + C::CastText(ops) => { + let cast_lhs = format!("({lhs}::text)"); + b.push("("); + for (i, op) in ops.iter().enumerate() { + if i > 0 { + b.push(" AND "); + } + emit_compare(b, &cast_lhs, op, "text"); + } + b.push(")"); + } + } +} + +/// For array-typed columns this deliberately reproduces Hasura v2.43's +/// broken `_in`/`_nin`: each element (itself an array, text form `{a,b}`) +/// is quoted into a flat 1-D array literal, losing dimensionality, so +/// Postgres rejects `col = ANY(...)` with "operator does not exist" and +/// the client sees the masked "database query error" — pinned by +/// snapshots/default/wm-array-in-database-error.json. Do not "fix" the +/// dimensionality. +fn emit_in_array(b: &mut Sql, vs: &[ir::SqlValue], pg_type: &str) { + let elem_cast = vs + .first() + .map(|v| v.cast.as_str()) + .unwrap_or(pg_type) + .to_string(); + b.param_array(vs.iter().map(|v| v.text.as_deref()), &elem_cast); +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::serve::model::Scalar; + + fn compile_root(pg_schema: &str, root: &ir::TableRoot) -> (String, Vec>) { + let c = compile_root_full(pg_schema, root); + (c.sql, c.params) + } + + fn col(alias: &str, column: &str, scalar: Scalar, pg_type: &str) -> ir::SelItem { + ir::SelItem::Column { + alias: alias.to_string(), + column: column.to_string(), + scalar, + pg_type: pg_type.to_string(), + is_array: false, + json_path: None, + } + } + + #[test] + fn many_with_where_order_limit() { + let root = ir::TableRoot { + alias: "User".to_string(), + table: "User".to_string(), + kind: ir::TableRootKind::Many { + args: ir::SelectArgs { + where_: Some(ir::BoolExp::Compare { + column: "id".to_string(), + scalar: Scalar::String, + pg_type: "text".to_string(), + is_array: false, + op: ir::CompareOp::Eq(ir::SqlValue::new("u1", "text")), + }), + order_by: vec![ir::OrderByItem { + target: ir::OrderTarget::Column { + column: "age".to_string(), + }, + direction: ir::OrderDirection::Desc, + }], + limit: Some(2), + offset: Some(1), + distinct_on: vec![], + }, + selection: ir::ObjectSelection { + table: "User".to_string(), + items: vec![ + col("id", "id", Scalar::String, "text"), + col("big", "big", Scalar::Numeric, "numeric"), + ir::SelItem::Typename { + alias: "__typename".to_string(), + type_name: "User".to_string(), + }, + ], + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert_eq!( + (sql.as_str(), params), + ( + "SELECT (coalesce(json_agg(\"_v\" ORDER BY \"_o0\" DESC NULLS FIRST), '[]'))::text AS \"root\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\", (\"t0\".\"big\")::text AS \"big\", 'User' AS \"__typename\") AS \"_e\")) AS \"_v\", \"t0\".\"age\" AS \"_o0\" \ + FROM (SELECT * FROM \"public\".\"User\" AS \"t0\" WHERE ((\"t0\".\"id\") = (($1)::text)) ORDER BY \"age\" DESC NULLS FIRST LIMIT (($2)::int8) OFFSET (($3)::int8)) AS \"t0\") AS \"_r\"", + vec![ + Some("u1".to_string()), + Some("2".to_string()), + Some("1".to_string()) + ] + ) + ); + } + + #[test] + fn directive_skipped_empty_selection_emits_empty_objects() { + let root = ir::TableRoot { + alias: "User".to_string(), + table: "User".to_string(), + kind: ir::TableRootKind::Many { + args: ir::SelectArgs::default(), + selection: ir::ObjectSelection { + table: "User".to_string(), + items: vec![], + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert!( + sql.contains("SELECT '{}'::json AS \"_v\""), + "empty selections must compile to valid empty JSON objects: {sql}" + ); + assert!(params.is_empty()); + } + + #[test] + fn by_pk() { + let root = ir::TableRoot { + alias: "u".to_string(), + table: "User".to_string(), + kind: ir::TableRootKind::ByPk { + pk: vec![("id".to_string(), ir::SqlValue::new("u1", "text"))], + selection: ir::ObjectSelection { + table: "User".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert_eq!( + (sql.as_str(), params), + ( + "SELECT (coalesce((json_agg(\"_v\")->0), 'null'))::text AS \"root\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\") AS \"_e\")) AS \"_v\" \ + FROM (SELECT * FROM \"public\".\"User\" AS \"t0\" WHERE ((\"t0\".\"id\") = (($1)::text))) AS \"t0\") AS \"_r\"", + vec![Some("u1".to_string())] + ) + ); + } + + #[test] + fn bool_exp_nesting_and_in() { + let root = ir::TableRoot { + alias: "T".to_string(), + table: "T".to_string(), + kind: ir::TableRootKind::Many { + args: ir::SelectArgs { + where_: Some(ir::BoolExp::And(vec![ + ir::BoolExp::Or(vec![]), + ir::BoolExp::Not(Box::new(ir::BoolExp::Compare { + column: "name".to_string(), + scalar: Scalar::String, + pg_type: "text".to_string(), + is_array: false, + op: ir::CompareOp::In(vec![ + ir::SqlValue::new("a\"b", "text"), + ir::SqlValue::new("c\\d", "text"), + ]), + })), + ir::BoolExp::Compare { + column: "name".to_string(), + scalar: Scalar::String, + pg_type: "text".to_string(), + is_array: false, + op: ir::CompareOp::IsNull(false), + }, + ])), + ..Default::default() + }, + selection: ir::ObjectSelection { + table: "T".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert_eq!( + (sql.as_str(), params), + ( + "SELECT (coalesce(json_agg(\"_v\"), '[]'))::text AS \"root\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\") AS \"_e\")) AS \"_v\" \ + FROM (SELECT * FROM \"public\".\"T\" AS \"t0\" WHERE (('false') AND (NOT ((\"t0\".\"name\") = ANY((($1)::text[])))) AND ((\"t0\".\"name\") IS NOT NULL))) AS \"t0\") AS \"_r\"", + vec![Some("{\"a\\\"b\",\"c\\\\d\"}".to_string())] + ) + ); + } + + #[test] + fn in_on_array_column_reproduces_hasura_error_shape() { + // Matches Hasura's broken flat-array encoding pinned by + // wm-array-in-database-error.json: elements keep their 1-D text + // form as quoted scalars while the cast gains a (meaningless) + // extra dimension, so Postgres errors on `text[] = text`. + let root = ir::TableRoot { + alias: "E".to_string(), + table: "E".to_string(), + kind: ir::TableRootKind::Many { + args: ir::SelectArgs { + where_: Some(ir::BoolExp::Compare { + column: "arrayOfStrings".to_string(), + scalar: Scalar::String, + pg_type: "text".to_string(), + is_array: true, + op: ir::CompareOp::In(vec![ + ir::SqlValue::new("{\"a\"}", "text[]"), + ir::SqlValue::new("{\"one\",\"two\"}", "text[]"), + ]), + }), + ..Default::default() + }, + selection: ir::ObjectSelection { + table: "E".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert_eq!( + (sql.as_str(), params), + ( + "SELECT (coalesce(json_agg(\"_v\"), '[]'))::text AS \"root\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\") AS \"_e\")) AS \"_v\" \ + FROM (SELECT * FROM \"public\".\"E\" AS \"t0\" WHERE ((\"t0\".\"arrayOfStrings\") = ANY((($1)::text[][])))) AS \"t0\") AS \"_r\"", + vec![Some( + "{\"{\\\"a\\\"}\",\"{\\\"one\\\",\\\"two\\\"}\"}".to_string() + )] + ) + ); + } + + #[test] + fn aggregate_with_nodes_and_typename() { + let root = ir::TableRoot { + alias: "User_aggregate".to_string(), + table: "User".to_string(), + kind: ir::TableRootKind::Aggregate { + args: ir::SelectArgs::default(), + selection: ir::AggregateSelection { + table: "User".to_string(), + items: vec![ + ir::AggSelItem::Typename { + alias: "__typename".to_string(), + type_name: "User_aggregate".to_string(), + }, + ir::AggSelItem::Aggregate { + alias: "aggregate".to_string(), + items: vec![ + ir::AggFieldItem::Count { + alias: "count".to_string(), + columns: vec![], + distinct: false, + }, + ir::AggFieldItem::Count { + alias: "c2".to_string(), + columns: vec!["a".to_string(), "b".to_string()], + distinct: true, + }, + ir::AggFieldItem::Op { + alias: "sum".to_string(), + op: "sum".to_string(), + columns: vec![ir::AggOpColumn::Column { + alias: "big".to_string(), + column: "big".to_string(), + scalar: Scalar::Numeric, + pg_type: "numeric".to_string(), + is_array: false, + op: "sum".to_string(), + }], + }, + ], + }, + ir::AggSelItem::Nodes { + alias: "nodes".to_string(), + selection: ir::ObjectSelection { + table: "User".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }, + ], + nodes_limit: None, + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert_eq!( + (sql.as_str(), params), + ( + "SELECT (json_build_object('__typename', coalesce('User_aggregate', (bool_or('true'))::text), \ + 'aggregate', json_build_object('count', count(*), 'c2', count(DISTINCT (\"_r\".\"_pc0\", \"_r\".\"_pc1\")), 'sum', json_build_object('big', (sum(\"_r\".\"_pc2\"))::text)), \ + 'nodes', coalesce(json_agg(\"_n0\"), '[]')))::text AS \"root\" \ + FROM (SELECT \"t0\".\"a\" AS \"_pc0\", \"t0\".\"b\" AS \"_pc1\", \"t0\".\"big\" AS \"_pc2\", \ + row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\") AS \"_e\")) AS \"_n0\" \ + FROM (SELECT * FROM \"public\".\"User\" AS \"t0\" WHERE ('true')) AS \"t0\") AS \"_r\"", + vec![] + ) + ); + } + + #[test] + fn aggregate_typename_only_gets_limit_1() { + // `X_aggregate { aggregate { __typename } }` compiles to no SQL + // aggregate function; without the LIMIT 1 the statement would + // return one identical constant row per table row. + let root = ir::TableRoot { + alias: "User_aggregate".to_string(), + table: "User".to_string(), + kind: ir::TableRootKind::Aggregate { + args: ir::SelectArgs::default(), + selection: ir::AggregateSelection { + table: "User".to_string(), + items: vec![ir::AggSelItem::Aggregate { + alias: "aggregate".to_string(), + items: vec![ir::AggFieldItem::Typename { + alias: "__typename".to_string(), + type_name: "User_aggregate_fields".to_string(), + }], + }], + nodes_limit: None, + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert_eq!( + (sql.as_str(), params), + ( + "SELECT (json_build_object('aggregate', json_build_object('__typename', 'User_aggregate_fields')))::text AS \"root\" \ + FROM (SELECT 1 FROM (SELECT * FROM \"public\".\"User\" AS \"t0\" WHERE ('true')) AS \"t0\") AS \"_r\" LIMIT 1", + vec![] + ) + ); + } + + #[test] + fn aggregate_nodes_limit_orders_row_numbers() { + let root = ir::TableRoot { + alias: "User_aggregate".to_string(), + table: "User".to_string(), + kind: ir::TableRootKind::Aggregate { + args: ir::SelectArgs { + order_by: vec![ir::OrderByItem { + target: ir::OrderTarget::Column { + column: "id".to_string(), + }, + direction: ir::OrderDirection::Asc, + }], + ..Default::default() + }, + selection: ir::AggregateSelection { + table: "User".to_string(), + items: vec![ir::AggSelItem::Nodes { + alias: "nodes".to_string(), + selection: ir::ObjectSelection { + table: "User".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }], + nodes_limit: Some(5), + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert_eq!( + (sql.as_str(), params), + ( + "SELECT (json_build_object('nodes', coalesce(json_agg(\"_n0\" ORDER BY \"_o0\" ASC NULLS LAST) FILTER (WHERE \"_rn\" <= 5), '[]')))::text AS \"root\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\") AS \"_e\")) AS \"_n0\", \ + row_number() OVER (ORDER BY \"t0\".\"id\" ASC NULLS LAST) AS \"_rn\", \"t0\".\"id\" AS \"_o0\" \ + FROM (SELECT * FROM \"public\".\"User\" AS \"t0\" WHERE ('true') ORDER BY \"id\" ASC NULLS LAST) AS \"t0\") AS \"_r\"", + vec![] + ) + ); + } + + #[test] + fn aggregate_nodes_limit_numbers_after_relationship_order_pagination() { + let root = ir::TableRoot { + alias: "Token_aggregate".to_string(), + table: "Token".to_string(), + kind: ir::TableRootKind::Aggregate { + args: ir::SelectArgs { + order_by: vec![ir::OrderByItem { + target: ir::OrderTarget::ObjectRelColumn { + path: vec![("owner_id".to_string(), "User".to_string())], + column: "id".to_string(), + }, + direction: ir::OrderDirection::Asc, + }], + offset: Some(5), + ..Default::default() + }, + selection: ir::AggregateSelection { + table: "Token".to_string(), + items: vec![ir::AggSelItem::Nodes { + alias: "nodes".to_string(), + selection: ir::ObjectSelection { + table: "Token".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }], + nodes_limit: Some(5), + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert!( + sql.contains("FROM (SELECT \"_p\".*, row_number() OVER"), + "row numbering must wrap the relationship-ordered OFFSET subquery: {sql}" + ); + assert_eq!(params, vec![Some("5".to_string())]); + } + + #[test] + fn bool_aggregate_predicate_empty_in_uses_bool_array_cast() { + let root = ir::TableRoot { + alias: "User".to_string(), + table: "User".to_string(), + kind: ir::TableRootKind::Many { + args: ir::SelectArgs { + where_: Some(ir::BoolExp::ArrayRelAggregate { + remote_column: "user_id".to_string(), + remote_table: "Token".to_string(), + pred: ir::AggregatePredicate { + op: "bool_and".to_string(), + columns: vec!["enabled".to_string()], + distinct: false, + filter: None, + predicate: vec![ir::CompareOp::In(vec![])], + }, + }), + ..Default::default() + }, + selection: ir::ObjectSelection { + table: "User".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert!( + sql.contains("::bool[]"), + "bool aggregate predicates need a boolean empty-array cast: {sql}" + ); + assert!(!sql.contains("::int4[]"), "unexpected integer cast: {sql}"); + assert_eq!(params, vec![Some("{}".to_string())]); + } + + #[test] + fn relationships_and_rel_order() { + let root = ir::TableRoot { + alias: "Gravatar".to_string(), + table: "Gravatar".to_string(), + kind: ir::TableRootKind::Many { + args: ir::SelectArgs { + order_by: vec![ir::OrderByItem { + target: ir::OrderTarget::ObjectRelColumn { + path: vec![("owner_id".to_string(), "User".to_string())], + column: "name".to_string(), + }, + direction: ir::OrderDirection::Asc, + }], + limit: Some(3), + ..Default::default() + }, + selection: ir::ObjectSelection { + table: "Gravatar".to_string(), + items: vec![ + col("id", "id", Scalar::String, "text"), + ir::SelItem::ObjectRel { + alias: "owner".to_string(), + local_column: "owner_id".to_string(), + remote_table: "User".to_string(), + selection: ir::ObjectSelection { + table: "User".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }, + ir::SelItem::ArrayRel { + alias: "tags".to_string(), + remote_column: "gravatar_id".to_string(), + remote_table: "Tag".to_string(), + args: ir::SelectArgs { + limit: Some(2), + ..Default::default() + }, + selection: ir::ObjectSelection { + table: "Tag".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }, + ], + }, + }, + }; + let (sql, params) = compile_root("public", &root); + assert_eq!( + (sql.as_str(), params), + ( + "SELECT (coalesce(json_agg(\"_v\" ORDER BY \"_o0\" ASC NULLS LAST), '[]'))::text AS \"root\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\", \"t1\".\"_v\" AS \"owner\", \"t2\".\"_v\" AS \"tags\") AS \"_e\")) AS \"_v\", \ + \"t3\".\"name\" AS \"_o0\" \ + FROM (SELECT * FROM \"public\".\"Gravatar\" AS \"t0\" WHERE ('true')) AS \"t0\" \ + LEFT JOIN \"public\".\"User\" AS \"t3\" ON ((\"t0\".\"owner_id\") = (\"t3\".\"id\")) \ + LEFT OUTER JOIN LATERAL (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t4\".\"id\" AS \"id\") AS \"_e\")) AS \"_v\" \ + FROM (SELECT * FROM \"public\".\"User\" AS \"t4\" WHERE ((\"t4\".\"id\") = (\"t0\".\"owner_id\")) LIMIT (($1)::int8)) AS \"t4\") AS \"t1\" ON ('true') \ + LEFT OUTER JOIN LATERAL (SELECT coalesce(json_agg(\"_v\"), '[]') AS \"_v\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t5\".\"id\" AS \"id\") AS \"_e\")) AS \"_v\" \ + FROM (SELECT * FROM \"public\".\"Tag\" AS \"t5\" WHERE ((\"t5\".\"gravatar_id\") = (\"t0\".\"id\")) LIMIT (($2)::int8)) AS \"t5\") AS \"_r\") AS \"t2\" ON ('true') \ + ORDER BY \"_o0\" ASC NULLS LAST LIMIT (($3)::int8)) AS \"_r\"", + vec![ + Some("1".to_string()), + Some("2".to_string()), + Some("3".to_string()) + ] + ) + ); + } + + fn stream_root(cursors: Vec) -> ir::TableRoot { + ir::TableRoot { + alias: "Token_stream".to_string(), + table: "Token".to_string(), + kind: ir::TableRootKind::Stream { + batch_size: 10, + cursor: cursors, + where_: None, + selection: ir::ObjectSelection { + table: "Token".to_string(), + items: vec![col("id", "id", Scalar::String, "text")], + }, + }, + } + } + + fn cursor( + column: &str, + initial_value: Option, + descending: bool, + ) -> ir::StreamCursor { + ir::StreamCursor { + column: column.to_string(), + cast: "numeric".to_string(), + initial_value, + descending, + } + } + + #[test] + fn stream_cursor_bound() { + let root = stream_root(vec![cursor( + "tokenId", + Some(ir::SqlValue::new("5", "numeric")), + false, + )]); + let c = compile_root_full("public", &root); + assert_eq!( + (c.sql.as_str(), c.params, c.cursor_slots), + ( + "SELECT (coalesce(json_agg(\"_v\" ORDER BY \"_o0\" ASC), '[]'))::text AS \"root\", \ + (array_agg((\"_o0\")::text ORDER BY \"_o0\" ASC))[count(*)] AS \"cursor_0\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\") AS \"_e\")) AS \"_v\", \"t0\".\"tokenId\" AS \"_o0\" \ + FROM (SELECT * FROM \"public\".\"Token\" AS \"t0\" WHERE ((\"t0\".\"tokenId\") > (($1)::numeric)) ORDER BY \"tokenId\" ASC LIMIT (($2)::int8)) AS \"t0\") AS \"_r\"", + vec![Some("5".to_string()), Some("10".to_string())], + vec![(0usize, 0usize)] + ) + ); + } + + #[test] + fn stream_cursor_null_position_asc_matches_nothing() { + // ASC = NULLS LAST: no rows sort strictly after a NULL position, + // so the stream drains but keeps polling with an empty result. + let root = stream_root(vec![cursor( + "tokenId", + Some(ir::SqlValue::null("numeric")), + false, + )]); + let c = compile_root_full("public", &root); + assert_eq!( + (c.sql.as_str(), c.params, c.cursor_slots), + ( + "SELECT (coalesce(json_agg(\"_v\" ORDER BY \"_o0\" ASC), '[]'))::text AS \"root\", \ + (array_agg((\"_o0\")::text ORDER BY \"_o0\" ASC))[count(*)] AS \"cursor_0\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\") AS \"_e\")) AS \"_v\", \"t0\".\"tokenId\" AS \"_o0\" \ + FROM (SELECT * FROM \"public\".\"Token\" AS \"t0\" WHERE ('false') ORDER BY \"tokenId\" ASC LIMIT (($1)::int8)) AS \"t0\") AS \"_r\"", + vec![Some("10".to_string())], + vec![] + ) + ); + } + + #[test] + fn stream_cursor_null_position_desc_matches_nothing_even_with_tiebreak() { + // Hasura does not reinterpret NULL according to NULLS FIRST/LAST. + // Its strict comparison remains unknown, so later cursor columns + // cannot make this branch match rows. + let root = stream_root(vec![ + cursor("blockNumber", Some(ir::SqlValue::null("numeric")), true), + cursor("logIndex", Some(ir::SqlValue::new("7", "numeric")), false), + ]); + let c = compile_root_full("public", &root); + assert_eq!( + (c.sql.as_str(), c.params, c.cursor_slots), + ( + "SELECT (coalesce(json_agg(\"_v\" ORDER BY \"_o0\" DESC, \"_o1\" ASC), '[]'))::text AS \"root\", \ + (array_agg((\"_o0\")::text ORDER BY \"_o0\" DESC, \"_o1\" ASC))[count(*)] AS \"cursor_0\", \ + (array_agg((\"_o1\")::text ORDER BY \"_o0\" DESC, \"_o1\" ASC))[count(*)] AS \"cursor_1\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\") AS \"_e\")) AS \"_v\", \"t0\".\"blockNumber\" AS \"_o0\", \"t0\".\"logIndex\" AS \"_o1\" \ + FROM (SELECT * FROM \"public\".\"Token\" AS \"t0\" WHERE ('false') ORDER BY \"blockNumber\" DESC, \"logIndex\" ASC LIMIT (($1)::int8)) AS \"t0\") AS \"_r\"", + vec![Some("10".to_string())], + vec![] + ) + ); + } + + #[test] + fn stream_two_bounded_cursors_record_all_slots() { + let root = stream_root(vec![ + cursor( + "blockNumber", + Some(ir::SqlValue::new("100", "numeric")), + false, + ), + cursor("logIndex", Some(ir::SqlValue::new("7", "numeric")), false), + ]); + let c = compile_root_full("public", &root); + assert_eq!( + (c.sql.as_str(), c.params, c.cursor_slots), + ( + "SELECT (coalesce(json_agg(\"_v\" ORDER BY \"_o0\" ASC, \"_o1\" ASC), '[]'))::text AS \"root\", \ + (array_agg((\"_o0\")::text ORDER BY \"_o0\" ASC, \"_o1\" ASC))[count(*)] AS \"cursor_0\", \ + (array_agg((\"_o1\")::text ORDER BY \"_o0\" ASC, \"_o1\" ASC))[count(*)] AS \"cursor_1\" \ + FROM (SELECT row_to_json((SELECT \"_e\" FROM (SELECT \"t0\".\"id\" AS \"id\") AS \"_e\")) AS \"_v\", \"t0\".\"blockNumber\" AS \"_o0\", \"t0\".\"logIndex\" AS \"_o1\" \ + FROM (SELECT * FROM \"public\".\"Token\" AS \"t0\" WHERE (((\"t0\".\"blockNumber\") > (($1)::numeric)) OR (((\"t0\".\"blockNumber\") = (($2)::numeric)) AND ((\"t0\".\"logIndex\") > (($3)::numeric)))) ORDER BY \"blockNumber\" ASC, \"logIndex\" ASC LIMIT (($4)::int8)) AS \"t0\") AS \"_r\"", + vec![ + Some("100".to_string()), + Some("100".to_string()), + Some("7".to_string()), + Some("10".to_string()) + ], + vec![(0usize, 0usize), (0usize, 1usize), (1usize, 2usize)] + ) + ); + } +} diff --git a/packages/cli/src/serve/exec/validate/args.rs b/packages/cli/src/serve/exec/validate/args.rs new file mode 100644 index 0000000000..499c725798 --- /dev/null +++ b/packages/cli/src/serve/exec/validate/args.rs @@ -0,0 +1,570 @@ +use super::bool_exp::coerce_bool_exp; +use super::coerce::{ + coerce_column_value, coerce_enum, coerce_limit, coerce_offset, coerce_string_strict, + column_pg_cast, parse_json_path, +}; +use super::selection::Flat; +use super::{ + found_desc, ir, model_table, q, verr, Ctx, FieldDef, GResult, Json, Table, TypeRef, V, +}; + +// --------------------------------------------------------------------------- +// Argument coercion: select args, by_pk, stream +// --------------------------------------------------------------------------- + +/// Looks up a provided argument and resolves variables against the +/// argument's declared type. Returns None when the argument was not given. +pub(super) fn resolve_arg<'a>( + ctx: &'a Ctx<'a>, + flat: &Flat<'a>, + field: &FieldDef, + name: &str, + field_path: &str, +) -> GResult>> { + let Some((_, raw)) = flat.args.iter().find(|(n, _)| n == name) else { + return Ok(None); + }; + let ivd = field + .args + .iter() + .find(|a| a.name == name) + .expect("argument definition must exist after unknown-arg check"); + let path = format!("{field_path}.args.{name}"); + Ok(Some(ctx.resolve( + raw, + &ivd.ty, + ivd.default_value.is_some(), + &path, + )?)) +} + +pub(super) fn coerce_select_args<'a>( + ctx: &'a Ctx<'a>, + flat: &Flat<'a>, + field: &FieldDef, + table_name: &str, + field_path: &str, + clamp: bool, +) -> GResult { + let table = model_table(ctx, table_name); + let mut args = ir::SelectArgs::default(); + + if let Some(v) = resolve_arg(ctx, flat, field, "where", field_path)? { + if !v.is_null() { + let path = format!("{field_path}.args.where"); + args.where_ = Some(coerce_bool_exp(ctx, table_name, v, &path)?); + } + } + if let Some(v) = resolve_arg(ctx, flat, field, "order_by", field_path)? { + if !v.is_null() { + let path = format!("{field_path}.args.order_by"); + args.order_by = coerce_order_by(ctx, table_name, v, &path)?; + } + } + if let Some(v) = resolve_arg(ctx, flat, field, "distinct_on", field_path)? { + if !v.is_null() { + let enum_name = format!("{table_name}_select_column"); + for (i, item) in list_items(v).into_iter().enumerate() { + let ipath = format!("{field_path}.args.distinct_on[{i}]"); + let api = coerce_enum(ctx, item, &enum_name, &ipath)?; + args.distinct_on.push(api_to_db_column(table, &api)); + } + } + } + if let Some(v) = resolve_arg(ctx, flat, field, "limit", field_path)? { + args.limit = coerce_limit(ctx, v, &format!("{field_path}.args.limit"))?; + } + if let Some(v) = resolve_arg(ctx, flat, field, "offset", field_path)? { + args.offset = coerce_offset(ctx, v, &format!("{field_path}.args.offset"))?; + } + + if !args.distinct_on.is_empty() && !args.order_by.is_empty() { + // Hasura: the first N order_by entries (N = distinct_on length, + // duplicates included) must all be plain columns and must contain + // every distinct_on column. + let n = args.distinct_on.len(); + let initial: Vec<&str> = args + .order_by + .iter() + .take(n) + .filter_map(|item| match &item.target { + ir::OrderTarget::Column { column } => Some(column.as_str()), + _ => None, + }) + .collect(); + let matches = initial.len() == n + && args + .distinct_on + .iter() + .all(|c| initial.contains(&c.as_str())); + if !matches { + return Err(verr( + format!("{field_path}.args"), + "\"distinct_on\" columns must match initial \"order_by\" columns", + )); + } + } + + if clamp { + if let Some(n) = ctx.response_limit { + args.limit = Some(args.limit.map_or(n, |l| l.min(n))); + } + } + Ok(args) +} + +pub(super) fn coerce_by_pk_args<'a>( + ctx: &'a Ctx<'a>, + flat: &Flat<'a>, + field: &FieldDef, + table_name: &str, + field_path: &str, +) -> GResult> { + let table = model_table(ctx, table_name); + let mut pk: Vec<(String, ir::SqlValue)> = Vec::new(); + for arg in &field.args { + let path = format!("{field_path}.args.{}", arg.name); + let Some(v) = resolve_arg(ctx, flat, field, &arg.name, field_path)? else { + return Err(verr(path, format!("missing required field '{}'", arg.name))); + }; + let col = table + .column_by_api_name(&arg.name) + .expect("by_pk argument must be a table column"); + let value = coerce_column_value( + ctx, + col.scalar, + &col.pg_type, + &col.pg_type_schema, + col.is_array, + v, + &path, + )?; + pk.push((col.db_name.clone(), value)); + } + Ok(pk) +} + +pub(super) fn coerce_stream_args<'a>( + ctx: &'a Ctx<'a>, + flat: &Flat<'a>, + field: &FieldDef, + table_name: &str, + field_path: &str, +) -> GResult<(i64, Vec, Option)> { + let batch_path = format!("{field_path}.args.batch_size"); + let mut batch_size = match resolve_arg(ctx, flat, field, "batch_size", field_path)? { + Some(v) => coerce_limit(ctx, v, &batch_path)? + .ok_or_else(|| verr(&batch_path, "unexpected null value for type 'Int'"))?, + None => return Err(verr(batch_path, "missing required field 'batch_size'")), + }; + if let Some(n) = ctx.response_limit { + batch_size = batch_size.min(n); + } + + let cursor_path = format!("{field_path}.args.cursor"); + let Some(cursor_v) = resolve_arg(ctx, flat, field, "cursor", field_path)? else { + return Err(verr(cursor_path, "missing required field 'cursor'")); + }; + let mut cursor: Vec = Vec::new(); + let table = model_table(ctx, table_name); + for (i, item) in expect_list(cursor_v, &cursor_path)?.into_iter().enumerate() { + if item.is_null() { + continue; + } + let ipath = format!("{cursor_path}[{i}]"); + let input_type = format!("{table_name}_stream_cursor_input"); + let entries = expect_object(item, &input_type, &ipath)?; + let type_def = ctx.registry.get(&input_type); + let mut initial: Option = None; + let mut descending = false; + for &(key, value) in &entries { + let Some(fd) = type_def.and_then(|d| d.input_field(key)) else { + return Err(verr( + format!("{ipath}.{key}"), + format!("field '{key}' not found in type: '{input_type}'"), + )); + }; + let vpath = format!("{ipath}.{key}"); + let v = resolve_nested(ctx, value, &fd.ty, fd.default_value.is_some(), &vpath)?; + match key { + "initial_value" => initial = Some(v), + "ordering" if !v.is_null() => { + let dir = coerce_enum(ctx, v, "cursor_ordering", &vpath)?; + descending = dir == "DESC"; + } + _ => {} + } + } + let init_path = format!("{ipath}.initial_value"); + let Some(initial) = initial else { + return Err(verr(init_path, "missing required field 'initial_value'")); + }; + let value_type = format!("{table_name}_stream_cursor_value_input"); + let value_def = ctx.registry.get(&value_type); + let cols = expect_object(initial, &value_type, &init_path)?; + for (key, value) in ordered_keys(table, cols) { + let Some(fd) = value_def.and_then(|d| d.input_field(key)) else { + return Err(verr( + format!("{init_path}.{key}"), + format!("field '{key}' not found in type: '{value_type}'"), + )); + }; + let vpath = format!("{init_path}.{key}"); + let v = resolve_nested(ctx, value, &fd.ty, fd.default_value.is_some(), &vpath)?; + let col = table + .column_by_api_name(key) + .expect("cursor value input field must be a table column"); + let cast = column_pg_cast(col.scalar, &col.pg_type, &col.pg_type_schema, col.is_array); + let initial_value = if v.is_null() { + Some(ir::SqlValue::null(cast.clone())) + } else { + Some(coerce_column_value( + ctx, + col.scalar, + &col.pg_type, + &col.pg_type_schema, + col.is_array, + v, + &vpath, + )?) + }; + cursor.push(ir::StreamCursor { + column: col.db_name.clone(), + cast, + initial_value, + descending, + }); + } + } + if cursor.is_empty() { + return Err(verr( + format!("{field_path}.args"), + "one streaming column field is expected", + )); + } + + let mut where_ = None; + if let Some(v) = resolve_arg(ctx, flat, field, "where", field_path)? { + if !v.is_null() { + let path = format!("{field_path}.args.where"); + where_ = Some(coerce_bool_exp(ctx, table_name, v, &path)?); + } + } + Ok((batch_size, cursor, where_)) +} + +/// json/jsonb column `path` argument. +pub(super) fn coerce_json_path_arg<'a>( + ctx: &'a Ctx<'a>, + flat: &Flat<'a>, + field: &FieldDef, + field_path: &str, +) -> GResult>> { + let Some(v) = resolve_arg(ctx, flat, field, "path", field_path)? else { + return Ok(None); + }; + let text = coerce_string_strict(v, &format!("{field_path}.args.path"))?; + match parse_json_path(&text) { + Ok(segments) => Ok(if segments.is_empty() { + None + } else { + Some(segments) + }), + Err(()) => Err(verr( + format!("{field_path}.args"), + format!( + "parse json path error: {text}. Accept letters, digits, underscore (_) or hyphen (-) only. Use quotes enclosed in bracket ([\"...\"]) if there is any special character" + ), + )), + } +} + +// --------------------------------------------------------------------------- +// Nested value plumbing +// --------------------------------------------------------------------------- + +/// Resolves one nesting level: literals may contain variables, JSON values +/// stay JSON all the way down. +pub(super) fn resolve_nested<'a>( + ctx: &'a Ctx<'a>, + v: V<'a>, + loc_ty: &TypeRef, + loc_has_default: bool, + path: &str, +) -> GResult> { + match v { + V::L(l) => ctx.resolve(l, loc_ty, loc_has_default, path), + j => Ok(j), + } +} + +/// List coercion: single non-null values coerce to one-element lists. +pub(super) fn list_items<'a>(v: V<'a>) -> Vec> { + match v { + V::L(q::Value::List(items)) => items.iter().map(V::L).collect(), + V::J(Json::Array(items)) => items.iter().map(V::J).collect(), + single => vec![single], + } +} + +pub(super) fn expect_list<'a>(v: V<'a>, path: &str) -> GResult>> { + if v.is_null() { + return Err(verr(path, "expected a list, but found null")); + } + Ok(list_items(v)) +} + +/// Sorted (key, value) entries of an input object, with the standard +/// "expected an object" error otherwise. +pub(super) fn expect_object<'a>( + v: V<'a>, + type_name: &str, + path: &str, +) -> GResult)>> { + match v { + V::L(q::Value::Object(map)) => { + Ok(map.iter().map(|(k, val)| (k.as_str(), V::L(val))).collect()) + } + V::J(Json::Object(map)) => Ok(map.iter().map(|(k, val)| (k.as_str(), V::J(val))).collect()), + other => Err(verr( + path, + format!( + "expected an object for type '{type_name}', but found {}", + found_desc(other) + ), + )), + } +} + +/// Reorders input-object keys: primary-key columns first (in key order), +/// then the rest alphabetically. Hasura's processing order is its HashMap's +/// hash order, which cannot be reproduced; this matches every order the +/// oracle snapshots pin. +fn ordered_keys<'a>(table: &Table, entries: Vec<(&'a str, V<'a>)>) -> Vec<(&'a str, V<'a>)> { + let pk_apis: Vec<&str> = table + .primary_key + .iter() + .filter_map(|db| table.columns.iter().find(|c| &c.db_name == db)) + .map(|c| c.api_name.as_str()) + .collect(); + let mut front: Vec<(&str, V)> = Vec::new(); + let mut rest: Vec<(&str, V)> = Vec::new(); + for entry in entries { + if pk_apis.contains(&entry.0) { + front.push(entry); + } else { + rest.push(entry); + } + } + front.sort_by_key(|(k, _)| pk_apis.iter().position(|p| p == k)); + front.extend(rest); + front +} + +pub(super) fn api_to_db_column(table: &Table, api_name: &str) -> String { + table + .column_by_api_name(api_name) + .map(|c| c.db_name.clone()) + .unwrap_or_else(|| api_name.to_string()) +} + +// --------------------------------------------------------------------------- +// order_by coercion +// --------------------------------------------------------------------------- + +fn order_direction(name: &str) -> ir::OrderDirection { + match name { + "asc" => ir::OrderDirection::Asc, + "asc_nulls_first" => ir::OrderDirection::AscNullsFirst, + "asc_nulls_last" => ir::OrderDirection::AscNullsLast, + "desc" => ir::OrderDirection::Desc, + "desc_nulls_first" => ir::OrderDirection::DescNullsFirst, + _ => ir::OrderDirection::DescNullsLast, + } +} + +fn coerce_order_by<'a>( + ctx: &'a Ctx<'a>, + table_name: &str, + v: V<'a>, + base_path: &str, +) -> GResult> { + let mut out: Vec = Vec::new(); + let elem_ty = TypeRef::non_null(TypeRef::named(&format!("{table_name}_order_by"))); + for (i, item) in list_items(v).into_iter().enumerate() { + let ipath = format!("{base_path}[{i}]"); + let item = resolve_item(ctx, item, &elem_ty, &ipath)?; + let mut chain: Vec<(String, String)> = Vec::new(); + expand_order_object(ctx, table_name, item, &ipath, &mut chain, &mut out)?; + } + Ok(out) +} + +pub(super) fn resolve_item<'a>( + ctx: &'a Ctx<'a>, + v: V<'a>, + elem_ty: &TypeRef, + path: &str, +) -> GResult> { + match v { + V::L(l) => ctx.resolve(l, elem_ty, false, path), + j => Ok(j), + } +} + +fn expand_order_object<'a>( + ctx: &'a Ctx<'a>, + table_name: &str, + v: V<'a>, + path: &str, + chain: &mut Vec<(String, String)>, + out: &mut Vec, +) -> GResult<()> { + let type_name = format!("{table_name}_order_by"); + let entries = expect_object(v, &type_name, path)?; + let table = model_table(ctx, table_name); + let type_def = ctx.registry.get(&type_name); + for (key, value) in ordered_keys(table, entries) { + let kpath = format!("{path}.{key}"); + let Some(fd) = type_def.and_then(|d| d.input_field(key)) else { + return Err(verr( + kpath, + format!("field '{key}' not found in type: '{type_name}'"), + )); + }; + let value = resolve_nested(ctx, value, &fd.ty, fd.default_value.is_some(), &kpath)?; + if value.is_null() { + continue; + } + if let Some(col) = table.column_by_api_name(key) { + let dir = coerce_enum(ctx, value, "order_by", &kpath)?; + let target = if chain.is_empty() { + ir::OrderTarget::Column { + column: col.db_name.clone(), + } + } else { + ir::OrderTarget::ObjectRelColumn { + path: chain.clone(), + column: col.db_name.clone(), + } + }; + out.push(ir::OrderByItem { + target, + direction: order_direction(&dir), + }); + } else if let Some(rel) = table.object_relationships.iter().find(|r| r.name == key) { + chain.push((rel.local_db_column.clone(), rel.remote_table.clone())); + expand_order_object(ctx, &rel.remote_table, value, &kpath, chain, out)?; + chain.pop(); + } else if let Some(rel) = key + .strip_suffix("_aggregate") + .and_then(|base| table.array_relationships.iter().find(|r| r.name == base)) + { + expand_aggregate_order(ctx, rel, value, &kpath, chain, out)?; + } else { + return Err(verr( + kpath, + format!("field '{key}' not found in type: '{type_name}'"), + )); + } + } + Ok(()) +} + +fn expand_aggregate_order<'a>( + ctx: &'a Ctx<'a>, + rel: &crate::serve::model::ArrayRelationship, + v: V<'a>, + path: &str, + chain: &[(String, String)], + out: &mut Vec, +) -> GResult<()> { + let remote = model_table(ctx, &rel.remote_table); + let type_name = format!("{}_aggregate_order_by", rel.remote_table); + let type_def = ctx.registry.get(&type_name); + for (op, value) in expect_object(v, &type_name, path)? { + let opath = format!("{path}.{op}"); + let Some(fd) = type_def.and_then(|d| d.input_field(op)) else { + return Err(verr( + opath, + format!("field '{op}' not found in type: '{type_name}'"), + )); + }; + let value = resolve_nested(ctx, value, &fd.ty, fd.default_value.is_some(), &opath)?; + if value.is_null() { + continue; + } + if op == "count" { + let dir = coerce_enum(ctx, value, "order_by", &opath)?; + out.push(ir::OrderByItem { + target: ir::OrderTarget::ArrayRelAggregate { + path: chain.to_vec(), + remote_column: rel.remote_db_column.clone(), + remote_table: rel.remote_table.clone(), + op: "count".to_string(), + column: None, + }, + direction: order_direction(&dir), + }); + } else { + let col_type = format!("{}_{op}_order_by", rel.remote_table); + let col_def = ctx.registry.get(&col_type); + for (col_key, col_value) in expect_object(value, &col_type, &opath)? { + let cpath = format!("{opath}.{col_key}"); + let Some(cfd) = col_def.and_then(|d| d.input_field(col_key)) else { + return Err(verr( + cpath, + format!("field '{col_key}' not found in type: '{col_type}'"), + )); + }; + let col_value = + resolve_nested(ctx, col_value, &cfd.ty, cfd.default_value.is_some(), &cpath)?; + if col_value.is_null() { + continue; + } + let dir = coerce_enum(ctx, col_value, "order_by", &cpath)?; + let col = remote + .column_by_api_name(col_key) + .expect("aggregate order_by field must be a column"); + out.push(ir::OrderByItem { + target: ir::OrderTarget::ArrayRelAggregate { + path: chain.to_vec(), + remote_column: rel.remote_db_column.clone(), + remote_table: rel.remote_table.clone(), + op: op.to_string(), + column: Some(col.db_name.clone()), + }, + direction: order_direction(&dir), + }); + } + } + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn order_direction_mapping() { + assert_eq!(order_direction("asc"), ir::OrderDirection::Asc); + assert_eq!( + order_direction("asc_nulls_first"), + ir::OrderDirection::AscNullsFirst + ); + assert_eq!( + order_direction("asc_nulls_last"), + ir::OrderDirection::AscNullsLast + ); + assert_eq!(order_direction("desc"), ir::OrderDirection::Desc); + assert_eq!( + order_direction("desc_nulls_first"), + ir::OrderDirection::DescNullsFirst + ); + assert_eq!( + order_direction("desc_nulls_last"), + ir::OrderDirection::DescNullsLast + ); + } +} diff --git a/packages/cli/src/serve/exec/validate/bool_exp.rs b/packages/cli/src/serve/exec/validate/bool_exp.rs new file mode 100644 index 0000000000..fd4fd30fe3 --- /dev/null +++ b/packages/cli/src/serve/exec/validate/bool_exp.rs @@ -0,0 +1,401 @@ +use super::args::{api_to_db_column, expect_list, expect_object, resolve_item, resolve_nested}; +use super::coerce::{coerce_bool_strict, coerce_column_value, coerce_enum, coerce_string_strict}; +use super::{ir, model_table, verr, Column, Ctx, GResult, Scalar, TypeRef, V}; + +// --------------------------------------------------------------------------- +// bool_exp coercion +// --------------------------------------------------------------------------- + +pub(super) fn coerce_bool_exp<'a>( + ctx: &'a Ctx<'a>, + table_name: &str, + v: V<'a>, + path: &str, +) -> GResult { + let type_name = format!("{table_name}_bool_exp"); + let entries = expect_object(v, &type_name, path)?; + let table = model_table(ctx, table_name); + let type_def = ctx.registry.get(&type_name); + + let mut parts: Vec = Vec::new(); + for (key, value) in entries { + let kpath = format!("{path}.{key}"); + let Some(fd) = type_def.and_then(|d| d.input_field(key)) else { + return Err(verr( + kpath, + format!("field '{key}' not found in type: '{type_name}'"), + )); + }; + let value = resolve_nested(ctx, value, &fd.ty, fd.default_value.is_some(), &kpath)?; + match key { + "_and" | "_or" => { + let items = expect_list(value, &kpath)?; + let mut inner: Vec = Vec::new(); + for (i, item) in items.into_iter().enumerate() { + let ipath = format!("{kpath}[{i}]"); + let elem_ty = TypeRef::non_null(TypeRef::named(&type_name)); + let item = resolve_item(ctx, item, &elem_ty, &ipath)?; + inner.push(coerce_bool_exp(ctx, table_name, item, &ipath)?); + } + parts.push(if key == "_and" { + ir::BoolExp::And(inner) + } else { + ir::BoolExp::Or(inner) + }); + } + "_not" => { + let inner = coerce_bool_exp(ctx, table_name, value, &kpath)?; + parts.push(ir::BoolExp::Not(Box::new(inner))); + } + _ => { + if let Some(col) = table.column_by_api_name(key) { + let ops = coerce_comparison(ctx, col, value, &kpath)?; + for op in ops { + parts.push(ir::BoolExp::Compare { + column: col.db_name.clone(), + scalar: col.scalar, + // `_in: []` has no value-level cast to infer from, + // so carry the complete scalar element cast as + // the SQL compiler's fallback. Array columns still + // use their element type here; `param_array` adds + // the outer list suffix. + pg_type: super::coerce::column_pg_cast( + col.scalar, + &col.pg_type, + &col.pg_type_schema, + false, + ), + is_array: col.is_array, + op, + }); + } + } else if let Some(rel) = table.object_relationships.iter().find(|r| r.name == key) + { + let inner = coerce_bool_exp(ctx, &rel.remote_table, value, &kpath)?; + parts.push(ir::BoolExp::ObjectRel { + local_column: rel.local_db_column.clone(), + remote_table: rel.remote_table.clone(), + exp: Box::new(inner), + }); + } else if let Some(rel) = table.array_relationships.iter().find(|r| r.name == key) { + let inner = coerce_bool_exp(ctx, &rel.remote_table, value, &kpath)?; + parts.push(ir::BoolExp::ArrayRel { + remote_column: rel.remote_db_column.clone(), + remote_table: rel.remote_table.clone(), + exp: Box::new(inner), + }); + } else if let Some(rel) = key + .strip_suffix("_aggregate") + .and_then(|base| table.array_relationships.iter().find(|r| r.name == base)) + { + let preds = coerce_aggregate_bool_exp(ctx, rel, value, &kpath)?; + parts.extend(preds); + } else { + return Err(verr( + kpath, + format!("field '{key}' not found in type: '{type_name}'"), + )); + } + } + } + } + Ok(if parts.len() == 1 { + parts.pop().unwrap() + } else { + ir::BoolExp::And(parts) + }) +} + +// --------------------------------------------------------------------------- +// Comparison expressions +// --------------------------------------------------------------------------- + +fn comparison_type_name(scalar: Scalar, pg_type: &str, is_array: bool) -> String { + let s = scalar.gql_name(pg_type); + if is_array { + format!("{s}_array_comparison_exp") + } else { + format!("{s}_comparison_exp") + } +} + +#[derive(Clone, Copy)] +struct ComparisonColumn<'a> { + scalar: Scalar, + pg_type: &'a str, + pg_type_schema: &'a str, + is_array: bool, +} + +fn coerce_comparison<'a>( + ctx: &'a Ctx<'a>, + col: &Column, + v: V<'a>, + path: &str, +) -> GResult> { + let type_name = comparison_type_name(col.scalar, &col.pg_type, col.is_array); + coerce_comparison_ops( + ctx, + ComparisonColumn { + scalar: col.scalar, + pg_type: &col.pg_type, + pg_type_schema: &col.pg_type_schema, + is_array: col.is_array, + }, + &type_name, + v, + path, + ) +} + +fn coerce_comparison_ops<'a>( + ctx: &'a Ctx<'a>, + column: ComparisonColumn<'_>, + type_name: &str, + v: V<'a>, + path: &str, +) -> GResult> { + let entries = expect_object(v, type_name, path)?; + let type_def = ctx.registry.get(type_name); + + let mut ops: Vec = Vec::new(); + for (op, value) in entries { + let opath = format!("{path}.{op}"); + // The registry defines exactly which operators exist per scalar; + // when the comparison type itself is absent (e.g. Int predicates + // with no int column anywhere), fall back to accepting the op. + if let Some(def) = type_def { + if def.input_field(op).is_none() { + return Err(verr( + opath, + format!("field '{op}' not found in type: '{type_name}'"), + )); + } + } + let loc = type_def.and_then(|d| d.input_field(op)); + let value = match loc { + Some(fd) => resolve_nested(ctx, value, &fd.ty, fd.default_value.is_some(), &opath)?, + None => value, + }; + let scalar_value = |v: V<'a>, p: &str| { + coerce_column_value( + ctx, + column.scalar, + column.pg_type, + column.pg_type_schema, + column.is_array, + v, + p, + ) + }; + let list_value = |v: V<'a>, p: &str| -> GResult> { + let items = expect_list(v, p)?; + let mut out = Vec::new(); + for (i, item) in items.into_iter().enumerate() { + out.push(scalar_value(item, &format!("{p}[{i}]"))?); + } + Ok(out) + }; + let compare = match op { + "_eq" => ir::CompareOp::Eq(scalar_value(value, &opath)?), + "_neq" => ir::CompareOp::Neq(scalar_value(value, &opath)?), + "_gt" => ir::CompareOp::Gt(scalar_value(value, &opath)?), + "_gte" => ir::CompareOp::Gte(scalar_value(value, &opath)?), + "_lt" => ir::CompareOp::Lt(scalar_value(value, &opath)?), + "_lte" => ir::CompareOp::Lte(scalar_value(value, &opath)?), + "_in" => ir::CompareOp::In(list_value(value, &opath)?), + "_nin" => ir::CompareOp::Nin(list_value(value, &opath)?), + "_is_null" => ir::CompareOp::IsNull(coerce_bool_strict(value, &opath)?), + "_like" => ir::CompareOp::Like(scalar_value(value, &opath)?), + "_nlike" => ir::CompareOp::Nlike(scalar_value(value, &opath)?), + "_ilike" => ir::CompareOp::Ilike(scalar_value(value, &opath)?), + "_nilike" => ir::CompareOp::Nilike(scalar_value(value, &opath)?), + "_similar" => ir::CompareOp::Similar(scalar_value(value, &opath)?), + "_nsimilar" => ir::CompareOp::Nsimilar(scalar_value(value, &opath)?), + "_regex" => ir::CompareOp::Regex(scalar_value(value, &opath)?), + "_iregex" => ir::CompareOp::Iregex(scalar_value(value, &opath)?), + "_nregex" => ir::CompareOp::Nregex(scalar_value(value, &opath)?), + "_niregex" => ir::CompareOp::Niregex(scalar_value(value, &opath)?), + "_contains" => ir::CompareOp::Contains(scalar_value(value, &opath)?), + "_contained_in" => ir::CompareOp::ContainedIn(scalar_value(value, &opath)?), + "_has_key" => { + let s = coerce_string_strict(value, &opath)?; + ir::CompareOp::HasKey(ir::SqlValue::new(s, "text")) + } + "_has_keys_all" | "_has_keys_any" => { + let items = expect_list(value, &opath)?; + let mut out = Vec::new(); + for (i, item) in items.into_iter().enumerate() { + let s = coerce_string_strict(item, &format!("{opath}[{i}]"))?; + out.push(ir::SqlValue::new(s, "text")); + } + if op == "_has_keys_all" { + ir::CompareOp::HasKeysAll(out) + } else { + ir::CompareOp::HasKeysAny(out) + } + } + "_cast" => { + let cast_entries = expect_object(value, "jsonb_cast_exp", &opath)?; + let mut inner: Vec = Vec::new(); + for (ck, cv) in cast_entries { + let cpath = format!("{opath}.{ck}"); + if ck != "String" { + return Err(verr( + cpath, + format!("field '{ck}' not found in type: 'jsonb_cast_exp'"), + )); + } + let text_ops = coerce_comparison_ops( + ctx, + ComparisonColumn { + scalar: Scalar::String, + pg_type: "text", + pg_type_schema: "pg_catalog", + is_array: false, + }, + "String_comparison_exp", + cv, + &cpath, + )?; + inner.extend(text_ops); + } + ir::CompareOp::CastText(inner) + } + other => { + return Err(verr( + opath, + format!("field '{other}' not found in type: '{type_name}'"), + )); + } + }; + ops.push(compare); + } + Ok(ops) +} + +// --------------------------------------------------------------------------- +// Aggregate predicates in bool_exp +// --------------------------------------------------------------------------- + +fn coerce_aggregate_bool_exp<'a>( + ctx: &'a Ctx<'a>, + rel: &crate::serve::model::ArrayRelationship, + v: V<'a>, + path: &str, +) -> GResult> { + let rt = &rel.remote_table; + let type_name = format!("{rt}_aggregate_bool_exp"); + let type_def = ctx.registry.get(&type_name); + let remote = model_table(ctx, rt); + + let mut out: Vec = Vec::new(); + for (op, value) in expect_object(v, &type_name, path)? { + let opath = format!("{path}.{op}"); + let Some(fd) = type_def.and_then(|d| d.input_field(op)) else { + return Err(verr( + opath, + format!("field '{op}' not found in type: '{type_name}'"), + )); + }; + let value = resolve_nested(ctx, value, &fd.ty, fd.default_value.is_some(), &opath)?; + let inner_type = format!("{rt}_aggregate_bool_exp_{op}"); + let inner_def = ctx.registry.get(&inner_type); + let entries = expect_object(value, &inner_type, &opath)?; + + let mut columns: Vec = Vec::new(); + let mut distinct = false; + let mut filter: Option> = None; + let mut predicate: Option> = None; + let mut has_arguments = false; + for (key, kv) in entries { + let kpath = format!("{opath}.{key}"); + let Some(kfd) = inner_def.and_then(|d| d.input_field(key)) else { + return Err(verr( + kpath, + format!("field '{key}' not found in type: '{inner_type}'"), + )); + }; + let kv = resolve_nested(ctx, kv, &kfd.ty, kfd.default_value.is_some(), &kpath)?; + match key { + "arguments" => { + has_arguments = true; + if op == "count" { + // Omitting `arguments` entirely means count(*) (the + // loop body above never runs, so `columns` stays + // empty); an explicit `null` is still a validation + // error, matching Hasura's "expected a list, but + // found null" for the analogous by-pk/eq cases. + let enum_name = format!("{rt}_select_column"); + for (i, item) in expect_list(kv, &kpath)?.into_iter().enumerate() { + let ipath = format!("{kpath}[{i}]"); + let api = coerce_enum(ctx, item, &enum_name, &ipath)?; + columns.push(api_to_db_column(remote, &api)); + } + } else { + // Non-count ops (bool_and/bool_or) require a single + // non-null column enum; let coerce_enum reject a null + // literal instead of silently emitting `op(*)`. + let enum_name = format!( + "{rt}_select_column_{rt}_aggregate_bool_exp_{op}_arguments_columns" + ); + let api = coerce_enum(ctx, kv, &enum_name, &kpath)?; + columns.push(api_to_db_column(remote, &api)); + } + } + "distinct" => { + distinct = coerce_bool_strict(kv, &kpath)?; + } + "filter" => { + if !kv.is_null() { + filter = Some(Box::new(coerce_bool_exp(ctx, rt, kv, &kpath)?)); + } + } + "predicate" => { + let (scalar, pg, cmp) = if op == "count" { + (Scalar::Int, "int4", "Int_comparison_exp") + } else { + (Scalar::Boolean, "bool", "Boolean_comparison_exp") + }; + predicate = Some(coerce_comparison_ops( + ctx, + ComparisonColumn { + scalar, + pg_type: pg, + pg_type_schema: "pg_catalog", + is_array: false, + }, + cmp, + kv, + &kpath, + )?); + } + _ => {} + } + } + let Some(predicate) = predicate else { + return Err(verr( + format!("{opath}.predicate"), + "missing required field 'predicate'", + )); + }; + if op != "count" && !has_arguments { + return Err(verr( + format!("{opath}.arguments"), + "missing required field 'arguments'", + )); + } + out.push(ir::BoolExp::ArrayRelAggregate { + remote_column: rel.remote_db_column.clone(), + remote_table: rt.clone(), + pred: ir::AggregatePredicate { + op: op.to_string(), + columns, + distinct, + filter, + predicate, + }, + }); + } + Ok(out) +} diff --git a/packages/cli/src/serve/exec/validate/coerce.rs b/packages/cli/src/serve/exec/validate/coerce.rs new file mode 100644 index 0000000000..d45b63bdaa --- /dev/null +++ b/packages/cli/src/serve/exec/validate/coerce.rs @@ -0,0 +1,912 @@ +use super::args::list_items; +use super::variables::VarValue; +use super::{ + aeson_kind, float_bounds_error, found_desc, int_bounds_error, ir, perr, q, verr, AValue, Ctx, + GResult, Json, Scalar, TypeDef, V, +}; + +// --------------------------------------------------------------------------- +// Strict (GraphQL-native) scalar coercion +// --------------------------------------------------------------------------- + +pub(super) fn coerce_bool_strict(v: V, path: &str) -> GResult { + match v { + V::L(q::Value::Boolean(b)) => Ok(*b), + V::J(Json::Bool(b)) => Ok(*b), + other => Err(verr( + path, + format!( + "expected a boolean for type 'Boolean', but found {}", + found_desc(other) + ), + )), + } +} + +pub(super) fn coerce_string_strict(v: V, path: &str) -> GResult { + match v { + V::L(q::Value::String(s)) => Ok(s.clone()), + V::J(Json::String(s)) => Ok(s.clone()), + other => Err(verr( + path, + format!( + "expected a string for type 'String', but found {}", + found_desc(other) + ), + )), + } +} + +/// Enum value coercion: GraphQL enum literals and JSON strings are valid, +/// string literals are not. +pub(super) fn coerce_enum(ctx: &Ctx, v: V, enum_type: &str, path: &str) -> GResult { + let name = match v { + V::L(q::Value::Enum(n)) => n.clone(), + V::J(Json::String(n)) => n.clone(), + V::L(q::Value::String(_)) => { + return Err(verr( + path, + format!("expected an enum value for type '{enum_type}', but found a string"), + )); + } + other => { + return Err(verr( + path, + format!( + "expected an enum value for type '{enum_type}', but found {}", + found_desc(other) + ), + )); + } + }; + let values = enum_values_for_message(ctx, enum_type); + if values.iter().any(|value| value == &name) { + Ok(name) + } else { + let list = values + .iter() + .map(|value| format!("'{value}'")) + .collect::>() + .join(", "); + Err(verr( + path, + format!( + "expected one of the values [{list}] for type '{enum_type}', but found '{name}'" + ), + )) + } +} + +/// Enum values in Hasura's HashMap-driven order: for select-column enums the +/// primary key comes first (which is all the snapshots pin); everything else +/// keeps registry (alphabetical) order. +fn enum_values_for_message(ctx: &Ctx, enum_type: &str) -> Vec { + let registry_values: Vec = match ctx.registry.get(enum_type) { + Some(TypeDef::Enum { values, .. }) => values.iter().map(|v| v.name.clone()).collect(), + _ => vec![], + }; + let Some(table) = enum_type + .strip_suffix("_select_column") + .and_then(|t| ctx.model.table(t)) + else { + return registry_values; + }; + let pk_apis: Vec<&str> = table + .primary_key + .iter() + .filter_map(|db| table.columns.iter().find(|c| &c.db_name == db)) + .map(|c| c.api_name.as_str()) + .collect(); + let mut out: Vec = pk_apis + .iter() + .filter(|pk| registry_values.iter().any(|v| v == *pk)) + .map(|pk| pk.to_string()) + .collect(); + for v in registry_values { + if !pk_apis.contains(&v.as_str()) { + out.push(v); + } + } + out +} + +/// Numeric value under coercion, keeping the original decimal text for +/// literals that overflow i64 so error displays and SQL keep full precision. +enum Num { + Small(i64), + Big(String), + Float(f64), +} + +fn numeric_of(ctx: &Ctx, v: V) -> Option { + match v { + V::L(q::Value::Int(n)) => { + let n = n.as_i64().unwrap_or(0); + Some(match ctx.int_originals.get(&n) { + Some(orig) => Num::Big(orig.clone()), + None => Num::Small(n), + }) + } + V::L(q::Value::Float(f)) => Some(match ctx.float_originals.get(&f.to_bits()) { + Some(orig) => Num::Big(orig.clone()), + None => Num::Float(*f), + }), + V::J(Json::Number(n)) => { + if let Some(i) = n.as_i64() { + Some(Num::Small(i)) + } else if let Some(u) = n.as_u64() { + Some(Num::Big(u.to_string())) + } else { + let f = n.as_f64()?; + Some(match ctx.var_number_originals.get(&f.to_bits()) { + Some(orig) => Num::Big(orig.clone()), + None => Num::Float(f), + }) + } + } + _ => None, + } +} + +impl Num { + fn display(&self, ctx: &Ctx) -> String { + match self { + Num::Small(n) => hs_scientific_decimal(&n.to_string()), + Num::Big(s) => hs_scientific_decimal(s), + Num::Float(f) => { + // f64-overflowing literals are rewritten to a unique finite + // sentinel per occurrence before parsing (see prescan.rs), + // so this is an exact per-occurrence lookup, not a guess by + // sign -- two distinct out-of-range literals in the same + // query each keep their own original text. + match ctx.inf_float_originals.get(&f.to_bits()) { + Some(orig) => hs_scientific_decimal(orig), + // Defensive: every f64-overflowing literal should have + // been rewritten already, so a genuinely infinite value + // here would be unexpected -- fall back to a plain + // Hasura-style display instead of losing the sign. + None if f.is_infinite() => { + if *f < 0.0 { + "-Infinity".to_string() + } else { + "Infinity".to_string() + } + } + None => hs_scientific_decimal(&format!("{f}")), + } + } + } + } + + /// Integral value within [min, max], or Err(display) Hasura-style. + fn as_int_bounded(&self, ctx: &Ctx, min: i64, max: i64) -> Result { + match self { + Num::Small(n) => { + if *n >= min && *n <= max { + Ok(*n) + } else { + Err(self.display(ctx)) + } + } + Num::Big(_) => Err(self.display(ctx)), + Num::Float(f) => { + if f.is_finite() && f.fract() == 0.0 && *f >= min as f64 && *f <= max as f64 { + Ok(*f as i64) + } else { + Err(self.display(ctx)) + } + } + } + } + + /// SQL text form (full precision for oversized literals). + fn sql_text(&self) -> String { + match self { + Num::Small(n) => n.to_string(), + Num::Big(s) => s.clone(), + Num::Float(f) => format!("{f}"), + } + } +} + +/// `limit` (and stream `batch_size`): non-negative 32-bit Int. GraphQL +/// float literals are a kind error; JSON numbers go through scientific +/// bounds checking (so 1.5 reports the bounds message instead). +pub(super) fn coerce_limit(ctx: &Ctx, v: V, path: &str) -> GResult> { + if v.is_null() { + return Ok(None); + } + let kind_err = |found: &str| { + verr( + path, + format!("expected a non-negative 32-bit integer for type 'Int', but found {found}"), + ) + }; + let num = match v { + V::L(q::Value::Int(_)) | V::J(Json::Number(_)) => numeric_of(ctx, v).unwrap(), + other => return Err(kind_err(found_desc(other))), + }; + match num.as_int_bounded(ctx, i32::MIN as i64, i32::MAX as i64) { + Ok(n) if n >= 0 => Ok(Some(n)), + Ok(_) => Err(kind_err("an integer")), + Err(display) => Err(int_bounds_error(path, &display)), + } +} + +/// `offset`: 32-bit ints, 64-bit ints, or 64-bit integers as strings +/// (oversized digit strings saturate, as observed against Hasura). +pub(super) fn coerce_offset(ctx: &Ctx, v: V, path: &str) -> GResult> { + if v.is_null() { + return Ok(None); + } + let kind_err = |found: &str| { + verr( + path, + format!( + "expected a 32-bit integer, or a 64-bit integer represented as a string for type 'Int', but found {found}" + ), + ) + }; + match v { + V::L(q::Value::Int(_)) | V::J(Json::Number(_)) => { + let num = numeric_of(ctx, v).unwrap(); + match num.as_int_bounded(ctx, i64::MIN, i64::MAX) { + Ok(n) => Ok(Some(n)), + Err(display) => Err(int_bounds_error(path, &display)), + } + } + V::L(q::Value::String(s)) | V::J(Json::String(s)) => match s.parse::() { + Ok(n) => Ok(Some(n)), + Err(_) => { + let digits = s.strip_prefix('-').unwrap_or(s); + if !digits.is_empty() && digits.bytes().all(|b| b.is_ascii_digit()) { + Ok(Some(if s.starts_with('-') { + i64::MIN + } else { + i64::MAX + })) + } else { + Err(kind_err("a string")) + } + } + }, + other => Err(kind_err(found_desc(other))), + } +} + +// --------------------------------------------------------------------------- +// Column-typed value coercion (comparison values, by_pk, stream cursors) +// --------------------------------------------------------------------------- + +fn quoted_pg_ident(name: &str) -> String { + format!("\"{}\"", name.replace('"', "\"\"")) +} + +pub(super) fn column_pg_cast( + scalar: Scalar, + pg_type: &str, + pg_type_schema: &str, + is_array: bool, +) -> String { + let base = match scalar { + Scalar::String => "text".to_string(), + Scalar::Int => "int4".to_string(), + Scalar::Smallint => "int2".to_string(), + Scalar::Bigint => "int8".to_string(), + Scalar::Float => "float4".to_string(), + Scalar::Float8 => "float8".to_string(), + Scalar::Numeric => "numeric".to_string(), + Scalar::Boolean => "bool".to_string(), + Scalar::Timestamptz => "timestamptz".to_string(), + Scalar::Timestamp => "timestamp".to_string(), + Scalar::Date => "date".to_string(), + Scalar::Jsonb => "jsonb".to_string(), + Scalar::Json => "json".to_string(), + Scalar::PgEnum | Scalar::Other if pg_type_schema != "pg_catalog" => format!( + "{}.{}", + quoted_pg_ident(pg_type_schema), + quoted_pg_ident(pg_type) + ), + Scalar::PgEnum | Scalar::Other => pg_type.to_string(), + }; + if is_array { + format!("{base}[]") + } else { + base + } +} + +pub(super) fn coerce_column_value<'a>( + ctx: &Ctx<'a>, + scalar: Scalar, + pg_type: &str, + pg_type_schema: &str, + is_array: bool, + v: V<'a>, + path: &str, +) -> GResult { + if v.is_null() { + let base = scalar.gql_name(pg_type); + let display = if is_array { format!("[{base}!]") } else { base }; + return Err(verr( + path, + format!("unexpected null value for type '{display}'"), + )); + } + if is_array { + let cast = column_pg_cast(scalar, pg_type, pg_type_schema, true); + let mut elems: Vec = Vec::new(); + for (i, item) in list_items(v).into_iter().enumerate() { + let elem = coerce_column_value( + ctx, + scalar, + pg_type, + pg_type_schema, + false, + item, + &format!("{path}[{i}]"), + )?; + elems.push(elem.text.unwrap_or_default()); + } + return Ok(ir::SqlValue::new(pg_array_literal(&elems), cast)); + } + + let cast = column_pg_cast(scalar, pg_type, pg_type_schema, false); + // Strings (and enum literals) always pass through: Hasura's typed parse + // falls back to an opaque value, so bad text errors in Postgres, not here. + let passthrough = match v { + V::L(q::Value::String(s)) | V::J(Json::String(s)) => Some(s.clone()), + V::L(q::Value::Enum(e)) => Some(e.clone()), + _ => None, + }; + + match scalar { + Scalar::Jsonb | Scalar::Json => Ok(ir::SqlValue::new(value_to_json_text(ctx, v)?, cast)), + Scalar::String => match passthrough { + Some(s) => Ok(ir::SqlValue::new(s, cast)), + None => Err(perr( + path, + format!( + "parsing Text failed, expected String, but encountered {}", + aeson_kind(v) + ), + )), + }, + Scalar::Timestamptz | Scalar::Timestamp | Scalar::Date => match passthrough { + Some(s) => Ok(ir::SqlValue::new(s, cast)), + None => { + let hs_type = match scalar { + Scalar::Timestamptz => "UTCTime", + Scalar::Timestamp => "LocalTime", + _ => "Day", + }; + Err(perr( + path, + format!( + "parsing {hs_type} failed, expected String, but encountered {}", + aeson_kind(v) + ), + )) + } + }, + Scalar::PgEnum | Scalar::Other => match passthrough { + Some(s) => Ok(ir::SqlValue::new(s, cast)), + None => Err(perr( + path, + format!("A string is expected for type: {pg_type}"), + )), + }, + Scalar::Boolean => match v { + V::L(q::Value::Boolean(b)) => Ok(ir::SqlValue::new(b.to_string(), cast)), + V::J(Json::Bool(b)) => Ok(ir::SqlValue::new(b.to_string(), cast)), + _ => match passthrough { + Some(s) => Ok(ir::SqlValue::new(s, cast)), + None => Err(perr( + path, + format!("expected Bool, but encountered {}", aeson_kind(v)), + )), + }, + }, + Scalar::Int | Scalar::Smallint | Scalar::Bigint => { + if let Some(s) = passthrough { + return Ok(ir::SqlValue::new(s, cast)); + } + let pg_name = match scalar { + Scalar::Int => "PGInteger", + Scalar::Smallint => "PGSmallInt", + _ => "PGBigInt", + }; + let (min, max) = match scalar { + Scalar::Int => (i32::MIN as i64, i32::MAX as i64), + Scalar::Smallint => (i16::MIN as i64, i16::MAX as i64), + _ => (i64::MIN, i64::MAX), + }; + let Some(num) = numeric_of(ctx, v) else { + return Err(perr( + path, + format!( + "parsing Integer expected for input type: {pg_name} failed, expected Number, but encountered {}", + aeson_kind(v) + ), + )); + }; + match num.as_int_bounded(ctx, min, max) { + Ok(n) => Ok(ir::SqlValue::new(n.to_string(), cast)), + Err(display) => Err(int_bounds_error(path, &display)), + } + } + Scalar::Numeric => { + if let Some(s) = passthrough { + return Ok(ir::SqlValue::new(s, cast)); + } + let Some(num) = numeric_of(ctx, v) else { + return Err(perr( + path, + format!( + "parsing Scientific failed, expected Number, but encountered {}", + aeson_kind(v) + ), + )); + }; + Ok(ir::SqlValue::new(num.sql_text(), cast)) + } + Scalar::Float | Scalar::Float8 => { + if let Some(s) = passthrough { + return Ok(ir::SqlValue::new(s, cast)); + } + let pg_name = if scalar == Scalar::Float { + "PGFloat" + } else { + "PGDouble" + }; + let overflowed_literal = match v { + V::L(q::Value::Float(f)) => ctx.inf_float_originals.contains_key(&f.to_bits()), + _ => false, + }; + let Some(num) = numeric_of(ctx, v) else { + return Err(perr( + path, + format!( + "parsing Float expected for input type: {pg_name} failed, expected Number, but encountered {}", + aeson_kind(v) + ), + )); + }; + if let Num::Big(original) = &num { + // Lossless JSON-number decoding keeps values such as 1e400 + // as original text. That is correct for numeric/jsonb, but + // Float/float8 must reject values outside f64 bounds during + // validation instead of handing Postgres an overflowing cast. + if !matches!(original.parse::(), Ok(f) if f.is_finite()) { + return Err(float_bounds_error(path, &num.display(ctx))); + } + } + if overflowed_literal { + return Err(float_bounds_error(path, &num.display(ctx))); + } + if let Num::Float(f) = &num { + // A literal that overflowed f64 is rewritten to a finite + // sentinel before parsing (see prescan.rs), so it no longer + // satisfies `is_infinite()` here -- check the sentinel map + // too, or an out-of-range literal like `1e400` would wrongly + // coerce instead of erroring like Hasura does. + if f.is_infinite() || ctx.inf_float_originals.contains_key(&f.to_bits()) { + return Err(float_bounds_error(path, &num.display(ctx))); + } + } + Ok(ir::SqlValue::new(num.sql_text(), cast)) + } + } +} + +/// Serializes a json/jsonb input directly to SQL parameter text. Writing +/// sentinel numbers as their original tokens avoids the lossy f64 hop that +/// a serde_json::Value round-trip would otherwise introduce. +fn value_to_json_text<'a>(ctx: &Ctx<'a>, v: V<'a>) -> GResult { + let mut out = String::new(); + match v { + V::J(j) => write_json_value(ctx, j, &mut out), + V::L(l) => write_json_literal(ctx, l, &mut out)?, + } + Ok(out) +} + +fn write_json_value(ctx: &Ctx, value: &Json, out: &mut String) { + match value { + Json::Null => out.push_str("null"), + Json::Bool(b) => out.push_str(if *b { "true" } else { "false" }), + Json::Number(n) => { + let original = n + .as_f64() + .and_then(|f| ctx.var_number_originals.get(&f.to_bits())); + out.push_str( + original + .map_or_else(|| n.to_string(), Clone::clone) + .as_str(), + ); + } + Json::String(s) => out.push_str(&serde_json::to_string(s).unwrap()), + Json::Array(items) => { + out.push('['); + for (i, item) in items.iter().enumerate() { + if i > 0 { + out.push(','); + } + write_json_value(ctx, item, out); + } + out.push(']'); + } + Json::Object(map) => { + out.push('{'); + for (i, (key, value)) in map.iter().enumerate() { + if i > 0 { + out.push(','); + } + out.push_str(&serde_json::to_string(key).unwrap()); + out.push(':'); + write_json_value(ctx, value, out); + } + out.push('}'); + } + } +} + +fn write_json_literal<'a>(ctx: &Ctx<'a>, value: &'a AValue, out: &mut String) -> GResult<()> { + match value { + q::Value::Null => out.push_str("null"), + q::Value::Boolean(b) => out.push_str(if *b { "true" } else { "false" }), + q::Value::Int(n) => { + let n = n.as_i64().unwrap_or(0); + out.push_str( + ctx.int_originals + .get(&n) + .map_or_else(|| n.to_string(), Clone::clone) + .as_str(), + ); + } + q::Value::Float(f) => out.push_str( + ctx.float_originals + .get(&f.to_bits()) + .map_or_else( + || { + serde_json::Number::from_f64(*f) + .map_or_else(|| "null".to_string(), |n| n.to_string()) + }, + Clone::clone, + ) + .as_str(), + ), + q::Value::String(s) | q::Value::Enum(s) => out.push_str(&serde_json::to_string(s).unwrap()), + q::Value::List(items) => { + out.push('['); + for (i, item) in items.iter().enumerate() { + if i > 0 { + out.push(','); + } + write_json_literal(ctx, item, out)?; + } + out.push(']'); + } + q::Value::Object(map) => { + out.push('{'); + for (i, (key, value)) in map.iter().enumerate() { + if i > 0 { + out.push(','); + } + out.push_str(&serde_json::to_string(key).unwrap()); + out.push(':'); + write_json_literal(ctx, value, out)?; + } + out.push('}'); + } + q::Value::Variable(name) => { + ctx.mark_used(name); + match ctx.vars.get(name.as_str()) { + Some(var) => match &var.value { + VarValue::Json(j) => write_json_value(ctx, j, out), + VarValue::Lit(l) => write_json_literal(ctx, l, out)?, + }, + None => return Err(verr("$", format!("unbound variable \"{name}\""))), + } + } + } + Ok(()) +} + +/// Postgres array literal text form, e.g. `{a,"b c"}`. +fn pg_array_literal(elems: &[String]) -> String { + let mut out = String::from("{"); + for (i, e) in elems.iter().enumerate() { + if i > 0 { + out.push(','); + } + let needs_quoting = e.is_empty() + || e.eq_ignore_ascii_case("null") + || e.chars() + .any(|c| matches!(c, '{' | '}' | ',' | '"' | '\\') || c.is_whitespace()); + if needs_quoting { + out.push('"'); + for c in e.chars() { + if c == '"' || c == '\\' { + out.push('\\'); + } + out.push(c); + } + out.push('"'); + } else { + out.push_str(e); + } + } + out.push('}'); + out +} + +// --------------------------------------------------------------------------- +// Hasura JSONPath parsing (json/jsonb `path` argument) +// --------------------------------------------------------------------------- + +/// Parses Hasura's JSONPath dialect into `#>` path segments. Accepted: +/// `$`, dotted names (unicode letters/digits/_/-, leading `$`/`.` optional), +/// `[123]` indexes, and `["..."]`/`['...']` quoted keys. +pub(super) fn parse_json_path(input: &str) -> Result, ()> { + if input == "$" { + return Ok(vec![]); + } + let mut chars = input.chars().peekable(); + if let Some('$') = chars.peek() { + chars.next(); + } + let mut segments: Vec = Vec::new(); + while chars.peek().is_some() { + if let Some('.') = chars.peek() { + chars.next(); + } + match chars.peek() { + Some('[') => { + chars.next(); + match chars.peek() { + Some(q @ '"') | Some(q @ '\'') => { + let quote = *q; + chars.next(); + let mut key = String::new(); + loop { + match chars.next() { + Some('\\') => match chars.next() { + Some(c) => key.push(c), + None => return Err(()), + }, + Some(c) if c == quote => break, + Some(c) => key.push(c), + None => return Err(()), + } + } + if chars.next() != Some(']') { + return Err(()); + } + segments.push(key); + } + Some(c) if c.is_ascii_digit() => { + let mut index = String::new(); + while let Some(c) = chars.peek() { + if c.is_ascii_digit() { + index.push(*c); + chars.next(); + } else { + break; + } + } + if chars.next() != Some(']') { + return Err(()); + } + segments.push(index); + } + _ => return Err(()), + } + } + Some(c) if *c == '_' || *c == '-' || c.is_alphanumeric() => { + let mut name = String::new(); + while let Some(c) = chars.peek() { + if *c == '_' || *c == '-' || c.is_alphanumeric() { + name.push(*c); + chars.next(); + } else { + break; + } + } + segments.push(name); + } + _ => return Err(()), + } + } + if segments.is_empty() { + return Err(()); + } + Ok(segments) +} + +// --------------------------------------------------------------------------- +// Haskell Scientific display (Data.Scientific Show) +// --------------------------------------------------------------------------- + +/// Formats a decimal literal the way Haskell shows a Scientific: +/// normalized digits, fixed notation for exponents 0..=7, otherwise +/// `d.ddde` (e.g. "5000000000" -> "5.0e9", "0.001" -> "1.0e-3"). +fn hs_scientific_decimal(s: &str) -> String { + let Some((neg, digits, e)) = parse_decimal(s) else { + return s.to_string(); + }; + hs_scientific_parts(neg, &digits, e) +} + +/// Splits a decimal/scientific literal into (negative, normalized mantissa +/// digits, e) with value = 0.digits * 10^e. +pub(super) fn parse_decimal(s: &str) -> Option<(bool, String, i64)> { + let s = s.trim(); + let (neg, s) = match s.strip_prefix('-') { + Some(rest) => (true, rest), + None => (false, s), + }; + let (mantissa, exp) = match s.find(['e', 'E']) { + Some(i) => (&s[..i], s[i + 1..].parse::().ok()?), + None => (s, 0), + }; + let (int_part, frac_part) = match mantissa.find('.') { + Some(i) => (&mantissa[..i], &mantissa[i + 1..]), + None => (mantissa, ""), + }; + if int_part.is_empty() && frac_part.is_empty() { + return None; + } + if !int_part.bytes().all(|b| b.is_ascii_digit()) + || !frac_part.bytes().all(|b| b.is_ascii_digit()) + { + return None; + } + let mut digits: String = format!("{int_part}{frac_part}"); + // A literal like `1e9223372036854775807` puts exp at i64::MAX; checked + // arithmetic falls back to echoing the raw text instead of overflowing + // (which would panic under debug assertions — a user-triggerable crash). + let mut e = (int_part.len() as i64).checked_add(exp)?; + let leading_zeros = digits.len() - digits.trim_start_matches('0').len(); + digits = digits[leading_zeros..].to_string(); + e = e.checked_sub(leading_zeros as i64)?; + digits = digits.trim_end_matches('0').to_string(); + if digits.is_empty() { + return Some((false, "0".to_string(), 0)); + } + Some((neg, digits, e)) +} + +fn hs_scientific_parts(neg: bool, digits: &str, e: i64) -> String { + let sign = if neg { "-" } else { "" }; + if !(0..=7).contains(&e) { + // Exponent format: first digit, '.', remaining digits (or 0), e. + // i128: e can legitimately sit at i64::MIN (e.g. `0.1e-9223372036854775808`). + let first = &digits[..1]; + let rest = if digits.len() > 1 { &digits[1..] } else { "0" }; + format!("{sign}{first}.{rest}e{}", (e as i128) - 1) + } else if e <= 0 { + format!("{sign}0.{}{digits}", "0".repeat((-e) as usize)) + } else { + let e = e as usize; + if digits.len() <= e { + format!("{sign}{digits}{}.0", "0".repeat(e - digits.len())) + } else { + format!("{sign}{}.{}", &digits[..e], &digits[e..]) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn scientific_display_matches_hasura() { + let cases = [ + ("1.5", "1.5"), + ("2147483648", "2.147483648e9"), + ("-2147483649", "-2.147483649e9"), + ("5000000000", "5.0e9"), + ("99999999999999", "9.9999999999999e13"), + ("9223372036854775808", "9.223372036854775808e18"), + ("99999999999999999999999", "9.9999999999999999999999e22"), + ("0.001", "1.0e-3"), + ("0.0025", "2.5e-3"), + ("2.5e-3", "2.5e-3"), + ("1e400", "1.0e400"), + ("100000000000000000000000000", "1.0e26"), + ("1.5e3", "1500.0"), + ("42", "42.0"), + ("5", "5.0"), + ("0.5", "0.5"), + ("0", "0.0"), + ("123.45", "123.45"), + // Exponents at the i64 boundary must not overflow the internal + // arithmetic (echoed raw when normalization can't represent them). + ("1e9223372036854775807", "1e9223372036854775807"), + ("1e-9223372036854775808", "1.0e-9223372036854775808"), + ("0.1e-9223372036854775807", "1.0e-9223372036854775808"), + ]; + for (input, expected) in cases { + assert_eq!( + (input, hs_scientific_decimal(input).as_str()), + (input, expected) + ); + } + } + + #[test] + fn json_path_parsing() { + let ok = [ + ("$", vec![]), + ("$.a.b", vec!["a", "b"]), + ("$.nested.a[0]", vec!["nested", "a", "0"]), + ("kind", vec!["kind"]), + (".kind", vec!["kind"]), + ("a.b", vec!["a", "b"]), + ("[0]", vec!["0"]), + ("$[2]", vec!["2"]), + ("['x']", vec!["x"]), + ("$[\"x y\"]", vec!["x y"]), + ("[\"a\\\"b\"]", vec!["a\"b"]), + ("$.héllo", vec!["héllo"]), + ("$[4].k", vec!["4", "k"]), + ("a-b_c1", vec!["a-b_c1"]), + ]; + for (input, expected) in ok { + assert_eq!( + parse_json_path(input), + Ok(expected.into_iter().map(String::from).collect::>()), + "{input}" + ); + } + for bad in [ + "", + "$.", + "a..b", + "$[", + "[x]", + "[12ab]", + "a b", + "$$", + "totally broken [", + ] { + assert_eq!(parse_json_path(bad), Err(()), "{bad}"); + } + } + + #[test] + fn pg_array_literal_quoting() { + assert_eq!( + pg_array_literal(&[ + "one".to_string(), + "two words".to_string(), + "a\"b\\c".to_string(), + "".to_string(), + "NULL".to_string(), + ]), + r#"{one,"two words","a\"b\\c","","NULL"}"# + ); + } + + #[test] + fn column_casts_qualify_custom_types_and_preserve_arrays() { + assert_eq!( + column_pg_cast(Scalar::PgEnum, "accounttype", "tenant", false), + r#""tenant"."accounttype""# + ); + assert_eq!( + column_pg_cast(Scalar::PgEnum, "accounttype", "tenant", true), + r#""tenant"."accounttype"[]"# + ); + assert_eq!( + column_pg_cast(Scalar::Other, "uuid", "pg_catalog", false), + "uuid" + ); + assert_eq!( + column_pg_cast(Scalar::PgEnum, "odd\"type", "odd\"schema", false), + r#""odd""schema"."odd""type""# + ); + } +} diff --git a/packages/cli/src/serve/exec/validate/fragments.rs b/packages/cli/src/serve/exec/validate/fragments.rs new file mode 100644 index 0000000000..b93ff6390c --- /dev/null +++ b/packages/cli/src/serve/exec/validate/fragments.rs @@ -0,0 +1,101 @@ +use super::{depth_error, q, verr, ASelSet, Ctx, GResult, MAX_DEPTH}; +use std::collections::HashMap; + +// --------------------------------------------------------------------------- +// Prepasses: fragment reachability, variable usage +// --------------------------------------------------------------------------- + +fn english_list(names: &[&str]) -> String { + match names.len() { + 0 => String::new(), + 1 => names[0].to_string(), + _ => format!( + "{} and {}", + names[..names.len() - 1].join(", "), + names[names.len() - 1] + ), + } +} + +/// Checks fragment reachability (undefined spreads, cycles) and returns the +/// selection depth of `set` after fragment expansion, so the caller can +/// enforce the nesting limit on what the later walkers will actually +/// recurse into. `depths` memoizes each fully-visited fragment's expanded +/// depth: without it, a chain of fragments each spread twice re-descends +/// exponentially. `frames` counts live recursion (selection nesting plus +/// spread descents) and is capped so a long fragment chain cannot overflow +/// the stack before the expanded-depth check runs. +pub(super) fn fragment_prepass<'a>( + ctx: &Ctx<'a>, + set: &'a ASelSet, + sel_path: &str, + stack: &mut Vec<&'a str>, + depths: &mut HashMap<&'a str, usize>, + frames: usize, +) -> GResult { + if frames > MAX_DEPTH { + return Err(depth_error()); + } + let mut depth = 0; + for item in &set.items { + match item { + q::Selection::Field(f) => { + let d = if !f.selection_set.items.is_empty() { + let inner = format!("{sel_path}.{}.selectionSet", f.name); + 1 + fragment_prepass(ctx, &f.selection_set, &inner, stack, depths, frames + 1)? + } else { + 1 + }; + depth = depth.max(d); + } + q::Selection::FragmentSpread(spread) => { + let name = spread.fragment_name.as_str(); + let Some(frag) = ctx.fragments.get(name) else { + return Err(verr( + sel_path, + format!("reference to undefined fragment \"{name}\""), + )); + }; + let d = match depths.get(name) { + Some(&d) => d, + None => { + if let Some(first) = stack.iter().position(|n| *n == name) { + return Err(verr( + sel_path, + format!( + "the fragment definition(s) {} form a cycle", + english_list(&stack[first..]) + ), + )); + } + stack.push(name); + let inner = format!("{sel_path}.{name}.selectionSet"); + let d = fragment_prepass( + ctx, + &frag.selection_set, + &inner, + stack, + depths, + frames + 1, + )?; + stack.pop(); + depths.insert(name, d); + d + } + }; + depth = depth.max(d); + } + q::Selection::InlineFragment(inline) => { + depth = depth.max(fragment_prepass( + ctx, + &inline.selection_set, + sel_path, + stack, + depths, + frames + 1, + )?); + } + } + } + Ok(depth) +} diff --git a/packages/cli/src/serve/exec/validate/json_numbers.rs b/packages/cli/src/serve/exec/validate/json_numbers.rs new file mode 100644 index 0000000000..97f5b4c3eb --- /dev/null +++ b/packages/cli/src/serve/exec/validate/json_numbers.rs @@ -0,0 +1,206 @@ +//! serde_json (without `arbitrary_precision`) rounds every non-64-bit-int +//! JSON number through f64, so variable values like +//! `99999999999999999999999` lose digits that Hasura's aeson `Scientific` +//! keeps. After validating the raw JSON grammar without materializing its +//! numbers, tokens whose text cannot round-trip through serde_json's +//! representation are rewritten to unique finite f64 sentinels. The decoder carries the resulting +//! sentinel-bits -> original-text map alongside (never inside) the +//! client-owned variables object, and the coercion layer substitutes the +//! original text back when producing SQL parameters. + +use super::coerce::parse_decimal; +use serde_json::value::RawValue; +use serde_json::Value as Json; +use std::collections::{HashMap, HashSet}; + +struct NumTok { + start: usize, + end: usize, +} + +/// Finds JSON number tokens in `src`, skipping string contents. Assumes +/// `src` has already been validated as JSON by `RawValue`. +fn number_tokens(src: &str) -> Vec { + let bytes = src.as_bytes(); + let mut out = Vec::new(); + let mut i = 0; + while i < bytes.len() { + match bytes[i] { + b'"' => { + i += 1; + while i < bytes.len() { + match bytes[i] { + b'\\' => i += 2, + b'"' => { + i += 1; + break; + } + _ => i += 1, + } + } + } + b'-' | b'0'..=b'9' => { + let start = i; + if bytes[i] == b'-' { + i += 1; + } + while i < bytes.len() + && matches!(bytes[i], b'0'..=b'9' | b'.' | b'e' | b'E' | b'+' | b'-') + { + i += 1; + } + out.push(NumTok { start, end: i }); + } + _ => i += 1, + } + } + out +} + +/// True when serde_json's parsed representation of `text` reaches SQL with +/// the same numeric value: i64/u64 integers are exact, and an f64 is exact +/// when the shortest decimal form it prints back equals the source text. +fn roundtrips(text: &str) -> bool { + let is_plain_int = !text.contains(['.', 'e', 'E']); + if is_plain_int && (text.parse::().is_ok() || text.parse::().is_ok()) { + return true; + } + let Ok(f) = text.parse::() else { + return false; + }; + if !f.is_finite() { + return false; + } + match (parse_decimal(text), parse_decimal(&format!("{f}"))) { + (Some(a), Some(b)) => a == b, + _ => false, + } +} + +/// Rewrites lossy number tokens in a JSON document to sentinel f64 values. +/// Returns None when every number round-trips as-is. +pub fn rewrite_lossy_numbers(src: &str) -> Option<(String, HashMap)> { + let toks = number_tokens(src); + let mut lossy: Vec<&NumTok> = Vec::new(); + let mut taken: HashSet = HashSet::new(); + for t in &toks { + let text = &src[t.start..t.end]; + if roundtrips(text) { + if let Ok(f) = text.parse::() { + taken.insert(f.to_bits()); + } + } else { + lossy.push(t); + } + } + if lossy.is_empty() { + return None; + } + + let mut originals: HashMap = HashMap::new(); + let mut sentinel = f64::MAX; + let mut out = String::with_capacity(src.len()); + let mut pos = 0; + for t in lossy { + // serde_json's default float parsing is not correctly rounded + // (that's its `float_roundtrip` feature), so the map must be keyed + // by the value serde_json will actually parse from the sentinel + // text — adjacent ULPs can collapse to the same f64. + let (text, bits) = loop { + let text = format!("{sentinel:e}"); + sentinel = f64::from_bits(sentinel.to_bits() - 1); + let Ok(parsed) = serde_json::from_str::(&text) else { + continue; + }; + let bits = parsed.to_bits(); + if !taken.contains(&bits) && !originals.contains_key(&bits) { + break (text, bits); + } + }; + originals.insert(bits, src[t.start..t.end].to_string()); + out.push_str(&src[pos..t.start]); + out.push_str(&text); + pos = t.end; + } + out.push_str(&src[pos..]); + Some((out, originals)) +} + +/// Validates JSON without first forcing its numbers through f64, then +/// materializes a `Value` after substituting finite sentinels for numbers +/// serde_json cannot otherwise represent. RawValue validation is important: +/// the lightweight number scanner deliberately assumes valid JSON and must +/// never turn a malformed token such as `1e` into an accepted request. +pub fn parse_value_preserving_numbers( + src: &str, +) -> Result<(Json, HashMap), serde_json::Error> { + let _: &RawValue = serde_json::from_str(src)?; + match rewrite_lossy_numbers(src) { + Some((rewritten, originals)) => Ok((serde_json::from_str::(&rewritten)?, originals)), + None => Ok((serde_json::from_str::(src)?, HashMap::new())), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ordinary_numbers_are_untouched() { + for src in [ + r#"{"v": 1.5}"#, + r#"{"v": -0}"#, + r#"{"v": 1e2, "w": [42, -7, 0.25]}"#, + r#"{"v": 9223372036854775807}"#, + r#"{"v": 18446744073709551615}"#, + r#"{"s": "99999999999999999999999"}"#, + ] { + assert!(rewrite_lossy_numbers(src).is_none(), "{src}"); + } + } + + #[test] + fn lossy_numbers_are_rewritten_and_recoverable() { + let src = r#"{"a": 99999999999999999999999, "b": 1.00000000000000000001, "c": 1.5}"#; + let (rewritten, originals) = rewrite_lossy_numbers(src).unwrap(); + let parsed: Json = serde_json::from_str(&rewritten).unwrap(); + let mut found: Vec<&String> = Vec::new(); + for key in ["a", "b"] { + let f = parsed[key].as_f64().unwrap(); + found.push(originals.get(&f.to_bits()).unwrap()); + } + assert_eq!( + ( + originals.len(), + found, + parsed["c"].as_f64(), + parsed["a"].as_i64(), + ), + ( + 2, + vec![ + &"99999999999999999999999".to_string(), + &"1.00000000000000000001".to_string() + ], + Some(1.5), + None, + ) + ); + } + + #[test] + fn raw_validation_accepts_overflow_but_rejects_malformed_numbers() { + let (parsed, originals) = + parse_value_preserving_numbers(r#"{"v":1e400,"nested":{"n":-9e999}}"#).unwrap(); + for (path, expected) in [(["v", ""], "1e400"), (["nested", "n"], "-9e999")] { + let value = if path[1].is_empty() { + &parsed[path[0]] + } else { + &parsed[path[0]][path[1]] + }; + let bits = value.as_f64().unwrap().to_bits(); + assert_eq!(originals.get(&bits).map(String::as_str), Some(expected)); + } + assert!(parse_value_preserving_numbers(r#"{"v":1e}"#).is_err()); + } +} diff --git a/packages/cli/src/serve/exec/validate/mod.rs b/packages/cli/src/serve/exec/validate/mod.rs new file mode 100644 index 0000000000..39ad11027e --- /dev/null +++ b/packages/cli/src/serve/exec/validate/mod.rs @@ -0,0 +1,1678 @@ +//! Parses and validates a GraphQL request against the role's registry, +//! producing the execution IR. All error messages/paths must match Hasura +//! byte-for-byte (see the oracle snapshots under +//! packages/e2e-tests/fixtures/differential/snapshots/). + +use super::error::{GResult, GraphQLError, CODE_PARSE_FAILED, CODE_VALIDATION_FAILED}; +use super::ir; +use super::{GraphQLRequest, Transport}; +use crate::serve::gql::schema_build::{Role, RoleSchema}; +use crate::serve::gql::types::{FieldDef, FieldKind, Registry, TypeDef, TypeRef}; +use crate::serve::model::{Column, Scalar, ServerModel, Table}; +use graphql_parser::query as q; +use serde_json::Value as Json; +use std::cell::RefCell; +use std::collections::{HashMap, HashSet}; + +mod args; +mod bool_exp; +mod coerce; +mod fragments; +pub mod json_numbers; +mod prescan; +mod selection; +mod variables; + +use args::{ + api_to_db_column, coerce_by_pk_args, coerce_json_path_arg, coerce_select_args, + coerce_stream_args, expect_list, resolve_arg, +}; +use coerce::{coerce_bool_strict, coerce_enum, coerce_string_strict}; +use fragments::fragment_prepass; +use prescan::prescan; +use selection::{collect_fields, Flat}; +use variables::{ + atype_display, atype_is_non_null, build_variables, variable_prepass, VarInfo, VarValue, +}; + +type AValue = q::Value<'static, String>; +type AType = q::Type<'static, String>; +type ASelSet = q::SelectionSet<'static, String>; +type ADirective = q::Directive<'static, String>; +type AVarDef = q::VariableDefinition<'static, String>; +type AFragment = q::FragmentDefinition<'static, String>; + +static NULL_LIT: AValue = q::Value::Null; + +// --------------------------------------------------------------------------- +// Errors +// --------------------------------------------------------------------------- + +fn verr(path: impl Into, message: impl Into) -> GraphQLError { + GraphQLError::validation(path, message) +} + +fn perr(path: impl Into, message: impl Into) -> GraphQLError { + GraphQLError { + message: message.into(), + path: path.into(), + code: CODE_PARSE_FAILED, + status: 200, + } +} + +/// Divergence from Hasura (which has no depth limit): nesting beyond this +/// would overflow the stack in graphql_parser and the recursive walkers. +const MAX_DEPTH: usize = 100; + +fn depth_error() -> GraphQLError { + verr( + "$.query", + format!("the query exceeds the maximum allowed nesting depth of {MAX_DEPTH}"), + ) +} + +/// Hasura reports syntax errors as validation-failed at `$.query`. +fn invalid_query() -> GraphQLError { + GraphQLError { + message: "not a valid graphql query".to_string(), + path: "$.query".to_string(), + code: CODE_VALIDATION_FAILED, + status: 200, + } +} + +fn int_bounds_error(path: &str, display: &str) -> GraphQLError { + perr( + path, + format!( + "The value {display} lies outside the bounds or is not an integer. Maybe it is a float, or is there integer overflow?" + ), + ) +} + +fn float_bounds_error(path: &str, display: &str) -> GraphQLError { + perr( + path, + format!("The value {display} lies outside the bounds. Is it overflowing the float bounds?"), + ) +} + +// --------------------------------------------------------------------------- +// Entry point +// --------------------------------------------------------------------------- + +/// Parse + validate + coerce a request into the execution IR. +/// +/// - `transport` gates the admissible operation types: subscriptions over +/// HTTP fail with `unexpected-payload`, but only after full validation +/// (Hasura validates the selection set first). +/// - The role's response limit (public role) is applied here by clamping +/// the effective SQL limit of table selects. +pub fn plan_request( + model: &ServerModel, + schema: &RoleSchema, + request: &GraphQLRequest, + transport: Transport, +) -> GResult { + if let Some(other) = request + .variables + .as_ref() + .filter(|v| !matches!(v, Json::Object(_) | Json::Null)) + { + return Err(perr( + "$.variables", + format!( + "parsing HashMap failed, expected Object, but encountered {}", + aeson_kind(V::J(other)) + ), + )); + } + let query_text = request.query.as_deref().unwrap_or(""); + let scan = prescan(query_text)?; + let doc = match q::parse_query::(&scan.rewritten) { + Ok(doc) => doc.into_static(), + Err(_) => return Err(invalid_query()), + }; + if doc.definitions.is_empty() { + return Err(invalid_query()); + } + + let mut operations: Vec = Vec::new(); + let mut fragment_defs: Vec<&AFragment> = Vec::new(); + for def in &doc.definitions { + match def { + q::Definition::Operation(op) => operations.push(OpParts::from_ast(op)), + q::Definition::Fragment(f) => fragment_defs.push(f), + } + } + + let op = select_operation(&operations, request.operation_name.as_deref())?; + check_operation_directives(op.kind, op.directives)?; + + // Hasura throws this before fragment/variable validation: the public + // role has no mutation parser at all. + if op.kind == OpKind::Mutation && schema.role == Role::Public { + return Err(verr("$", "no mutations exist")); + } + + let mut fragments: HashMap<&str, &AFragment> = HashMap::new(); + for f in &fragment_defs { + if fragments.insert(f.name.as_str(), f).is_some() { + return Err(perr( + "$", + format!("multiple definitions for fragment \"{}\"", f.name), + )); + } + } + + let variables_json = match &request.variables { + Some(Json::Object(m)) => Some(m), + _ => None, + }; + + let ctx = Ctx { + model, + registry: &schema.registry, + response_limit: if schema.role == Role::Public { + model.response_limit.map(|n| n as i64) + } else { + None + }, + fragments, + vars: build_variables(op.var_defs, variables_json)?, + used_vars: RefCell::new(HashSet::new()), + int_originals: scan.int_originals, + float_originals: scan.float_originals, + inf_float_originals: scan.inf_float_originals, + var_number_originals: request.variable_number_originals.clone(), + }; + + // Fragment reachability (undefined spreads, cycles) is checked before + // variables, which are checked before any schema validation — matching + // Hasura's inline -> resolveVariables -> parse pipeline. + let expanded_depth = fragment_prepass( + &ctx, + op.selection_set, + "$.selectionSet", + &mut Vec::new(), + &mut HashMap::new(), + 0, + )?; + if expanded_depth > MAX_DEPTH { + return Err(depth_error()); + } + variable_prepass(&ctx, op.selection_set)?; + if let Some(vars) = variables_json { + let used = ctx.used_vars.borrow(); + let unexpected: Vec<&str> = vars + .keys() + .filter(|k| !used.contains(k.as_str())) + .map(|k| k.as_str()) + .collect(); + if !unexpected.is_empty() { + return Err(verr( + "$", + format!( + "unexpected variables in variableValues: {}", + unexpected.join(", ") + ), + )); + } + } + + let kind = match op.kind { + OpKind::Query => ir::OperationKind::Query, + OpKind::Subscription => ir::OperationKind::Subscription, + OpKind::Mutation => return plan_admin_mutation(&ctx, op.selection_set), + }; + let root_fields = plan_roots(&ctx, kind, op.selection_set)?; + + if kind == ir::OperationKind::Subscription { + if root_fields.len() != 1 { + return Err(verr("$", "subscriptions must select one top level field")); + } + if transport == Transport::Http { + return Err(GraphQLError::unexpected_payload( + "subscriptions are not supported over HTTP, use websockets instead", + )); + } + } + + Ok(ir::Operation { kind, root_fields }) +} + +// --------------------------------------------------------------------------- +// Operation selection +// --------------------------------------------------------------------------- + +#[derive(Clone, Copy, PartialEq, Eq)] +enum OpKind { + Query, + Mutation, + Subscription, +} + +struct OpParts<'a> { + kind: OpKind, + name: Option<&'a str>, + var_defs: &'a [AVarDef], + directives: &'a [ADirective], + selection_set: &'a ASelSet, +} + +impl<'a> OpParts<'a> { + fn from_ast(op: &'a q::OperationDefinition<'static, String>) -> OpParts<'a> { + match op { + q::OperationDefinition::SelectionSet(set) => OpParts { + kind: OpKind::Query, + name: None, + var_defs: &[], + directives: &[], + selection_set: set, + }, + q::OperationDefinition::Query(x) => OpParts { + kind: OpKind::Query, + name: x.name.as_deref(), + var_defs: &x.variable_definitions, + directives: &x.directives, + selection_set: &x.selection_set, + }, + q::OperationDefinition::Mutation(x) => OpParts { + kind: OpKind::Mutation, + name: x.name.as_deref(), + var_defs: &x.variable_definitions, + directives: &x.directives, + selection_set: &x.selection_set, + }, + q::OperationDefinition::Subscription(x) => OpParts { + kind: OpKind::Subscription, + name: x.name.as_deref(), + var_defs: &x.variable_definitions, + directives: &x.directives, + selection_set: &x.selection_set, + }, + } + } +} + +fn is_valid_graphql_name(s: &str) -> bool { + let mut chars = s.chars(); + match chars.next() { + Some(c) if c == '_' || c.is_ascii_alphabetic() => {} + _ => return false, + } + chars.all(|c| c == '_' || c.is_ascii_alphanumeric()) +} + +fn select_operation<'a, 'b>( + ops: &'b [OpParts<'a>], + operation_name: Option<&str>, +) -> GResult<&'b OpParts<'a>> { + match operation_name { + Some(name) => { + if !is_valid_graphql_name(name) { + return Err(perr( + "$.operationName", + format!("{name} is not valid GraphQL name"), + )); + } + if ops.iter().any(|o| o.name.is_none()) { + return Err(verr( + "$", + "operationName cannot be used when an anonymous operation exists in the document", + )); + } + ops.iter().find(|o| o.name == Some(name)).ok_or_else(|| { + verr( + "$", + format!("no such operation found in the document: \"{name}\""), + ) + }) + } + None => { + if ops.len() == 1 { + Ok(&ops[0]) + } else { + Err(verr( + "$", + "exactly one operation has to be present in the document when operationName is not specified", + )) + } + } + } +} + +fn check_operation_directives(kind: OpKind, directives: &[ADirective]) -> GResult<()> { + let location = match kind { + OpKind::Query => "query", + OpKind::Mutation => "mutation", + OpKind::Subscription => "subscription", + }; + for d in directives { + match d.name.as_str() { + "include" | "skip" => { + return Err(verr( + "$", + format!("directive '{}' is not allowed on a {location}", d.name), + )); + } + // Hasura accepts @cached on queries (a no-op without caching). + "cached" => {} + other => { + return Err(verr( + "$", + format!("directive '{other}' is not defined in the schema"), + )); + } + } + } + Ok(()) +} + +// --------------------------------------------------------------------------- +// Context and values +// --------------------------------------------------------------------------- + +struct Ctx<'a> { + model: &'a ServerModel, + registry: &'a Registry, + response_limit: Option, + fragments: HashMap<&'a str, &'a AFragment>, + vars: HashMap<&'a str, VarInfo<'a>>, + used_vars: RefCell>, + /// i64-overflowing int literals were rewritten to magic sentinel values + /// before parsing; this maps each sentinel back to the original digits. + int_originals: HashMap, + /// Float literals whose exact decimal text cannot round-trip through + /// graphql-parser's f64 AST representation. Each is rewritten to a + /// unique sentinel and restored here for numeric SQL parameters. + float_originals: HashMap, + /// f64-overflowing float literals were rewritten to per-occurrence + /// finite sentinel values before parsing; this maps each sentinel's bit + /// pattern back to the original digits, for reconstructing Hasura's + /// error display of values the AST can no longer represent. + inf_float_originals: HashMap, + /// JSON variable numbers that cannot round-trip through serde_json's + /// f64 were rewritten to sentinel values before body parsing (see + /// json_numbers.rs); maps each sentinel's bit pattern back to the + /// original number text. + var_number_originals: HashMap, +} + +/// A value under coercion: either a GraphQL literal or a JSON value that +/// arrived through a variable. Hasura distinguishes the two in error +/// messages ("an integer" vs "a number", strict vs scientific ints). +#[derive(Clone, Copy)] +enum V<'a> { + L(&'a AValue), + J(&'a Json), +} + +impl<'a> V<'a> { + fn is_null(&self) -> bool { + matches!(self, V::L(q::Value::Null) | V::J(Json::Null)) + } +} + +/// Value-kind description used by the GraphQL-native (strict) parsers. +fn found_desc(v: V) -> &'static str { + match v { + V::L(l) => match l { + q::Value::Int(_) => "an integer", + q::Value::Float(_) => "a float", + q::Value::String(_) => "a string", + q::Value::Boolean(_) => "a boolean", + q::Value::Null => "null", + q::Value::Enum(_) => "an enum value", + q::Value::List(_) => "a list", + q::Value::Object(_) => "an object", + q::Value::Variable(_) => "a variable", + }, + V::J(j) => match j { + Json::Null => "null", + Json::Bool(_) => "a boolean", + Json::Number(_) => "a number", + Json::String(_) => "a string", + Json::Array(_) => "a list", + Json::Object(_) => "an object", + }, + } +} + +/// Value-kind name as aeson prints it in "encountered X" messages. +fn aeson_kind(v: V) -> &'static str { + match v { + V::L(l) => match l { + q::Value::Int(_) | q::Value::Float(_) => "Number", + q::Value::String(_) | q::Value::Enum(_) => "String", + q::Value::Boolean(_) => "Boolean", + q::Value::Null => "Null", + q::Value::List(_) => "Array", + q::Value::Object(_) => "Object", + q::Value::Variable(_) => "Null", + }, + V::J(j) => match j { + Json::Null => "Null", + Json::Bool(_) => "Boolean", + Json::Number(_) => "Number", + Json::String(_) => "String", + Json::Array(_) => "Array", + Json::Object(_) => "Object", + }, + } +} + +impl<'a> Ctx<'a> { + fn mark_used(&self, name: &'a str) { + self.used_vars.borrow_mut().insert(name); + } + + /// Resolves a possibly-variable value at an input location, type-checking + /// the variable's declared type against the location type. + fn resolve( + &'a self, + value: &'a AValue, + loc_ty: &TypeRef, + loc_has_default: bool, + path: &str, + ) -> GResult> { + match value { + q::Value::Variable(name) => { + self.mark_used(name); + let var = self + .vars + .get(name.as_str()) + .ok_or_else(|| verr("$", format!("unbound variable \"{name}\"")))?; + let compatible = types_compatible(loc_ty, var.ty); + let allowed = compatible + && (!loc_ty.is_non_null() + || atype_is_non_null(var.ty) + || loc_has_default + || matches!(var.default, Some(d) if !matches!(d, q::Value::Null))); + if !allowed { + return Err(verr( + path, + format!( + "variable '{name}' is declared as '{}', but used where '{}' is expected", + atype_display(var.ty), + loc_ty.display() + ), + )); + } + Ok(match &var.value { + VarValue::Json(j) => V::J(j), + VarValue::Lit(l) => V::L(l), + }) + } + other => Ok(V::L(other)), + } + } +} + +/// Structural compatibility ignoring nullability at each level, as Hasura's +/// areTypesCompatible does. +fn types_compatible(loc: &TypeRef, var: &AType) -> bool { + let loc = match loc { + TypeRef::NonNull(inner) => inner, + other => other, + }; + let var = match var { + q::Type::NonNullType(inner) => inner, + other => other, + }; + match (loc, var) { + (TypeRef::Named(a), q::Type::NamedType(b)) => a == b, + (TypeRef::List(li), q::Type::ListType(vi)) => types_compatible(li, vi), + _ => false, + } +} + +// --------------------------------------------------------------------------- +// Root planning +// --------------------------------------------------------------------------- + +fn plan_roots<'a>( + ctx: &'a Ctx<'a>, + kind: ir::OperationKind, + set: &'a ASelSet, +) -> GResult> { + let root_type = match kind { + ir::OperationKind::Query => ctx.registry.query_root.as_str(), + ir::OperationKind::Subscription => ctx.registry.subscription_root.as_str(), + }; + let sel_path = "$.selectionSet"; + let flats = collect_fields(ctx, root_type, &[set], sel_path)?; + let root_def = ctx.registry.get(root_type); + + let mut roots: Vec = Vec::new(); + for flat in &flats { + let field_path = format!("{sel_path}.{}", flat.name); + if flat.name == "__typename" { + check_leaf_field(flat, &field_path)?; + roots.push(ir::RootField::Typename { + alias: flat.key.clone(), + }); + continue; + } + if kind == ir::OperationKind::Query && (flat.name == "__schema" || flat.name == "__type") { + if let Some(root) = plan_introspection(ctx, flat, &field_path)? { + roots.push(root); + continue; + } + } + let Some(field) = root_def.and_then(|d| d.field(flat.name)) else { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{root_type}'", flat.name), + )); + }; + check_unknown_args(flat, field, &field_path)?; + let root = match &field.kind { + FieldKind::SelectMany { table } => { + let args = coerce_select_args(ctx, flat, field, table, &field_path, true)?; + let selection = require_object_selection(ctx, flat, table, &field_path)?; + ir::RootField::Table(ir::TableRoot { + alias: flat.key.clone(), + table: table.clone(), + kind: ir::TableRootKind::Many { args, selection }, + }) + } + FieldKind::SelectByPk { table } => { + let pk = coerce_by_pk_args(ctx, flat, field, table, &field_path)?; + let selection = require_object_selection(ctx, flat, table, &field_path)?; + ir::RootField::Table(ir::TableRoot { + alias: flat.key.clone(), + table: table.clone(), + kind: ir::TableRootKind::ByPk { pk, selection }, + }) + } + FieldKind::SelectAggregate { table } => { + let args = coerce_select_args(ctx, flat, field, table, &field_path, false)?; + let selection = require_aggregate_selection(ctx, flat, table, &field_path)?; + ir::RootField::Table(ir::TableRoot { + alias: flat.key.clone(), + table: table.clone(), + kind: ir::TableRootKind::Aggregate { args, selection }, + }) + } + FieldKind::SelectStream { table } => { + let (batch_size, cursor, where_) = + coerce_stream_args(ctx, flat, field, table, &field_path)?; + let selection = require_object_selection(ctx, flat, table, &field_path)?; + ir::RootField::Table(ir::TableRoot { + alias: flat.key.clone(), + table: table.clone(), + kind: ir::TableRootKind::Stream { + batch_size, + cursor, + where_, + selection, + }, + }) + } + _ => { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{root_type}'", flat.name), + )); + } + }; + roots.push(root); + } + Ok(roots) +} + +/// Admin mutations: the registry has no mutation types yet, but real Hasura +/// resolves unknown mutation fields against 'mutation_root', so walk the +/// selection with an empty virtual type to reproduce those errors. +fn plan_admin_mutation<'a>(ctx: &'a Ctx<'a>, set: &'a ASelSet) -> GResult { + let sel_path = "$.selectionSet"; + let flats = collect_fields(ctx, "mutation_root", &[set], sel_path)?; + for flat in &flats { + if flat.name == "__typename" { + continue; + } + if let Some(root_name) = &ctx.registry.mutation_root { + if ctx + .registry + .get(root_name) + .and_then(|d| d.field(flat.name)) + .is_some() + { + continue; + } + } + return Err(verr( + format!("{sel_path}.{}", flat.name), + format!("field '{}' not found in type: 'mutation_root'", flat.name), + )); + } + Err(verr("$", "no mutations exist")) +} + +fn check_unknown_args(flat: &Flat, field: &FieldDef, field_path: &str) -> GResult<()> { + for (name, _) in flat.args { + if !field.args.iter().any(|a| &a.name == name) { + return Err(verr( + field_path, + format!("'{}' has no argument named '{name}'", flat.name), + )); + } + } + Ok(()) +} + +/// Leaf fields take no arguments and no sub-selection. +fn check_leaf_field(flat: &Flat, field_path: &str) -> GResult<()> { + if let Some((name, _)) = flat.args.first() { + return Err(verr( + field_path, + format!("'{}' has no argument named '{name}'", flat.name), + )); + } + if flat.had_selection { + return Err(verr( + field_path, + "unexpected subselection set for non-object field", + )); + } + Ok(()) +} + +fn require_object_selection<'a>( + ctx: &'a Ctx<'a>, + flat: &Flat<'a>, + table: &str, + field_path: &str, +) -> GResult { + if !flat.had_selection { + return Err(verr( + format!("{field_path}.selectionSet"), + format!("missing selection set for '{}'", flat.name), + )); + } + object_selection( + ctx, + table, + &flat.sel_sets, + &format!("{field_path}.selectionSet"), + ) +} + +fn require_aggregate_selection<'a>( + ctx: &'a Ctx<'a>, + flat: &Flat<'a>, + table: &str, + field_path: &str, +) -> GResult { + if !flat.had_selection { + return Err(verr( + format!("{field_path}.selectionSet"), + format!("missing selection set for '{}'", flat.name), + )); + } + aggregate_selection( + ctx, + table, + &flat.sel_sets, + &format!("{field_path}.selectionSet"), + ) +} + +// --------------------------------------------------------------------------- +// Table selections +// --------------------------------------------------------------------------- + +fn model_table<'a>(ctx: &'a Ctx, name: &str) -> &'a Table { + ctx.model + .table(name) + .expect("registry table missing from model") +} + +fn object_selection<'a>( + ctx: &'a Ctx<'a>, + table_name: &str, + sets: &[&'a ASelSet], + sel_path: &str, +) -> GResult { + let flats = collect_fields(ctx, table_name, sets, sel_path)?; + let type_def = ctx.registry.get(table_name); + let table = model_table(ctx, table_name); + + let mut items: Vec = Vec::new(); + for flat in &flats { + let field_path = format!("{sel_path}.{}", flat.name); + if flat.name == "__typename" { + check_leaf_field(flat, &field_path)?; + items.push(ir::SelItem::Typename { + alias: flat.key.clone(), + type_name: table_name.to_string(), + }); + continue; + } + let Some(field) = type_def.and_then(|d| d.field(flat.name)) else { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{table_name}'", flat.name), + )); + }; + check_unknown_args(flat, field, &field_path)?; + match &field.kind { + FieldKind::Column { column } => { + if flat.had_selection { + return Err(verr( + &field_path, + "unexpected subselection set for non-object field", + )); + } + let col = table + .column_by_api_name(column) + .expect("registry column missing from model"); + let json_path = coerce_json_path_arg(ctx, flat, field, &field_path)?; + items.push(ir::SelItem::Column { + alias: flat.key.clone(), + column: col.db_name.clone(), + scalar: col.scalar, + pg_type: col.pg_type.clone(), + is_array: col.is_array, + json_path, + }); + } + FieldKind::ObjectRel { rel } => { + let rel = table + .object_relationships + .iter() + .find(|r| &r.name == rel) + .expect("registry object rel missing from model"); + let selection = + require_object_selection(ctx, flat, &rel.remote_table, &field_path)?; + items.push(ir::SelItem::ObjectRel { + alias: flat.key.clone(), + local_column: rel.local_db_column.clone(), + remote_table: rel.remote_table.clone(), + selection, + }); + } + FieldKind::ArrayRel { rel } => { + let rel = table + .array_relationships + .iter() + .find(|r| &r.name == rel) + .expect("registry array rel missing from model"); + let args = + coerce_select_args(ctx, flat, field, &rel.remote_table, &field_path, true)?; + let selection = + require_object_selection(ctx, flat, &rel.remote_table, &field_path)?; + items.push(ir::SelItem::ArrayRel { + alias: flat.key.clone(), + remote_column: rel.remote_db_column.clone(), + remote_table: rel.remote_table.clone(), + args, + selection, + }); + } + FieldKind::ArrayRelAggregate { rel } => { + let rel = table + .array_relationships + .iter() + .find(|r| &r.name == rel) + .expect("registry array rel missing from model"); + let args = + coerce_select_args(ctx, flat, field, &rel.remote_table, &field_path, false)?; + let selection = + require_aggregate_selection(ctx, flat, &rel.remote_table, &field_path)?; + items.push(ir::SelItem::ArrayRelAggregate { + alias: flat.key.clone(), + remote_column: rel.remote_db_column.clone(), + remote_table: rel.remote_table.clone(), + args, + selection, + }); + } + _ => { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{table_name}'", flat.name), + )); + } + } + } + Ok(ir::ObjectSelection { + table: table_name.to_string(), + items, + }) +} + +fn aggregate_selection<'a>( + ctx: &'a Ctx<'a>, + table_name: &str, + sets: &[&'a ASelSet], + sel_path: &str, +) -> GResult { + let agg_type = format!("{table_name}_aggregate"); + let flats = collect_fields(ctx, &agg_type, sets, sel_path)?; + let type_def = ctx.registry.get(&agg_type); + + let mut items: Vec = Vec::new(); + for flat in &flats { + let field_path = format!("{sel_path}.{}", flat.name); + if flat.name == "__typename" { + check_leaf_field(flat, &field_path)?; + items.push(ir::AggSelItem::Typename { + alias: flat.key.clone(), + type_name: agg_type.clone(), + }); + continue; + } + let Some(field) = type_def.and_then(|d| d.field(flat.name)) else { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{agg_type}'", flat.name), + )); + }; + check_unknown_args(flat, field, &field_path)?; + match &field.kind { + FieldKind::AggregateBody => { + if !flat.had_selection { + return Err(verr( + format!("{field_path}.selectionSet"), + format!("missing selection set for '{}'", flat.name), + )); + } + let body_items = aggregate_body( + ctx, + table_name, + &flat.sel_sets, + &format!("{field_path}.selectionSet"), + )?; + items.push(ir::AggSelItem::Aggregate { + alias: flat.key.clone(), + items: body_items, + }); + } + FieldKind::AggregateNodes => { + let selection = require_object_selection(ctx, flat, table_name, &field_path)?; + items.push(ir::AggSelItem::Nodes { + alias: flat.key.clone(), + selection, + }); + } + _ => { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{agg_type}'", flat.name), + )); + } + } + } + Ok(ir::AggregateSelection { + table: table_name.to_string(), + items, + // Hasura computes the aggregate over the uncapped set but caps the + // rows `nodes` returns at the role's response limit + // (limits-public-aggregate-count-exceeds-limit). + nodes_limit: ctx.response_limit, + }) +} + +fn aggregate_body<'a>( + ctx: &'a Ctx<'a>, + table_name: &str, + sets: &[&'a ASelSet], + sel_path: &str, +) -> GResult> { + let fields_type = format!("{table_name}_aggregate_fields"); + let flats = collect_fields(ctx, &fields_type, sets, sel_path)?; + let type_def = ctx.registry.get(&fields_type); + let table = model_table(ctx, table_name); + + let mut items: Vec = Vec::new(); + for flat in &flats { + let field_path = format!("{sel_path}.{}", flat.name); + if flat.name == "__typename" { + check_leaf_field(flat, &field_path)?; + items.push(ir::AggFieldItem::Typename { + alias: flat.key.clone(), + type_name: fields_type.clone(), + }); + continue; + } + let Some(field) = type_def.and_then(|d| d.field(flat.name)) else { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{fields_type}'", flat.name), + )); + }; + check_unknown_args(flat, field, &field_path)?; + match &field.kind { + FieldKind::AggregateCount => { + if flat.had_selection { + return Err(verr( + &field_path, + "unexpected subselection set for non-object field", + )); + } + let mut columns: Vec = Vec::new(); + if let Some(v) = resolve_arg(ctx, flat, field, "columns", &field_path)? { + let columns_path = format!("{field_path}.args.columns"); + let enum_name = format!("{table_name}_select_column"); + for (i, item) in expect_list(v, &columns_path)?.into_iter().enumerate() { + let ipath = format!("{columns_path}[{i}]"); + let api = coerce_enum(ctx, item, &enum_name, &ipath)?; + columns.push(api_to_db_column(table, &api)); + } + } + let distinct = match resolve_arg(ctx, flat, field, "distinct", &field_path)? { + Some(v) => coerce_bool_strict(v, &format!("{field_path}.args.distinct"))?, + None => false, + }; + items.push(ir::AggFieldItem::Count { + alias: flat.key.clone(), + columns, + distinct, + }); + } + FieldKind::AggregateOp { op } => { + if !flat.had_selection { + return Err(verr( + format!("{field_path}.selectionSet"), + format!("missing selection set for '{}'", flat.name), + )); + } + let columns = aggregate_op_columns( + ctx, + table_name, + op, + &flat.sel_sets, + &format!("{field_path}.selectionSet"), + )?; + items.push(ir::AggFieldItem::Op { + alias: flat.key.clone(), + op: op.clone(), + columns, + }); + } + _ => { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{fields_type}'", flat.name), + )); + } + } + } + Ok(items) +} + +fn aggregate_op_columns<'a>( + ctx: &'a Ctx<'a>, + table_name: &str, + op: &str, + sets: &[&'a ASelSet], + sel_path: &str, +) -> GResult> { + let op_type = format!("{table_name}_{op}_fields"); + let flats = collect_fields(ctx, &op_type, sets, sel_path)?; + let type_def = ctx.registry.get(&op_type); + let table = model_table(ctx, table_name); + + let mut columns: Vec = Vec::new(); + for flat in &flats { + let field_path = format!("{sel_path}.{}", flat.name); + if flat.name == "__typename" { + check_leaf_field(flat, &field_path)?; + columns.push(ir::AggOpColumn::Typename { + alias: flat.key.clone(), + type_name: op_type.clone(), + }); + continue; + } + let Some(field) = type_def.and_then(|d| d.field(flat.name)) else { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{op_type}'", flat.name), + )); + }; + check_unknown_args(flat, field, &field_path)?; + if flat.had_selection { + return Err(verr( + &field_path, + "unexpected subselection set for non-object field", + )); + } + match &field.kind { + FieldKind::AggregateOpColumn { op, column } => { + let col = table + .column_by_api_name(column) + .expect("registry column missing from model"); + columns.push(ir::AggOpColumn::Column { + alias: flat.key.clone(), + column: col.db_name.clone(), + scalar: col.scalar, + pg_type: col.pg_type.clone(), + is_array: col.is_array, + op: op.clone(), + }); + } + _ => { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{op_type}'", flat.name), + )); + } + } + } + Ok(columns) +} + +// --------------------------------------------------------------------------- +// Introspection planning +// --------------------------------------------------------------------------- + +/// Returns None when the meta types are absent from the registry, in which +/// case the caller falls through to the regular unknown-field error. +fn plan_introspection<'a>( + ctx: &'a Ctx<'a>, + flat: &Flat<'a>, + field_path: &str, +) -> GResult> { + let meta_type = match flat.name { + "__schema" => "__Schema", + _ => "__Type", + }; + if ctx.registry.get(meta_type).is_none() { + return Ok(None); + } + + let mut type_name: Option = None; + if flat.name == "__type" { + for (name, _) in flat.args { + if name != "name" { + return Err(verr( + field_path, + format!("'{}' has no argument named '{name}'", flat.name), + )); + } + } + let name_path = format!("{field_path}.args.name"); + let Some((_, raw)) = flat.args.iter().find(|(n, _)| n == "name") else { + return Err(verr(name_path, "missing required field 'name'")); + }; + let loc_ty = TypeRef::non_null(TypeRef::named("String")); + let v = ctx.resolve(raw, &loc_ty, false, &name_path)?; + type_name = Some(coerce_string_strict(v, &name_path)?); + } else if let Some((name, _)) = flat.args.first() { + return Err(verr( + field_path, + format!("'{}' has no argument named '{name}'", flat.name), + )); + } + + if !flat.had_selection { + return Err(verr( + format!("{field_path}.selectionSet"), + format!("missing selection set for '{}'", flat.name), + )); + } + let selection = intro_selection( + ctx, + meta_type, + &flat.sel_sets, + &format!("{field_path}.selectionSet"), + )?; + Ok(Some(ir::RootField::Introspection(ir::IntrospectionField { + alias: flat.key.clone(), + field: flat.name.to_string(), + type_name, + selection, + }))) +} + +fn intro_selection<'a>( + ctx: &'a Ctx<'a>, + meta_type: &str, + sets: &[&'a ASelSet], + sel_path: &str, +) -> GResult { + let flats = collect_fields(ctx, meta_type, sets, sel_path)?; + let type_def = ctx.registry.get(meta_type); + + let mut items: Vec = Vec::new(); + for flat in &flats { + let field_path = format!("{sel_path}.{}", flat.name); + if flat.name == "__typename" { + check_leaf_field(flat, &field_path)?; + items.push(ir::IntroSelItem { + alias: flat.key.clone(), + field: "__typename".to_string(), + include_deprecated: false, + selection: None, + }); + continue; + } + let Some(field) = type_def.and_then(|d| d.field(flat.name)) else { + return Err(verr( + &field_path, + format!("field '{}' not found in type: '{meta_type}'", flat.name), + )); + }; + check_unknown_args(flat, field, &field_path)?; + let include_deprecated = + match resolve_arg(ctx, flat, field, "includeDeprecated", &field_path)? { + Some(v) if !v.is_null() => { + coerce_bool_strict(v, &format!("{field_path}.args.includeDeprecated"))? + } + _ => false, + }; + let base = field.ty.base_name(); + let is_object = matches!(ctx.registry.get(base), Some(TypeDef::Object { .. })); + let selection = if is_object { + if !flat.had_selection { + return Err(verr( + format!("{field_path}.selectionSet"), + format!("missing selection set for '{}'", flat.name), + )); + } + Some(intro_selection( + ctx, + base, + &flat.sel_sets, + &format!("{field_path}.selectionSet"), + )?) + } else { + if flat.had_selection { + return Err(verr( + &field_path, + "unexpected subselection set for non-object field", + )); + } + None + }; + items.push(ir::IntroSelItem { + alias: flat.key.clone(), + field: flat.name.to_string(), + include_deprecated, + selection, + }); + } + Ok(ir::IntroSelection { items }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::serve::gql::schema_build; + use crate::serve::pg_catalog::RelationKind; + + #[test] + fn graphql_name_validation() { + assert!(is_valid_graphql_name("Query1")); + assert!(is_valid_graphql_name("_a")); + assert!(!is_valid_graphql_name("")); + assert!(!is_valid_graphql_name("9x")); + assert!(!is_valid_graphql_name("a-b")); + } + + fn column(name: &str, pg_type: &str, scalar: Scalar) -> Column { + Column { + api_name: name.to_string(), + db_name: name.to_string(), + pg_type: pg_type.to_string(), + pg_type_schema: "pg_catalog".to_string(), + scalar, + is_array: false, + nullable: false, + description: None, + } + } + + fn test_model() -> ServerModel { + ServerModel { + tables: vec![Table { + name: "User".to_string(), + kind: RelationKind::Table, + description: None, + columns: vec![ + column("id", "text", Scalar::String), + column("big", "numeric", Scalar::Numeric), + column("floating", "float8", Scalar::Float8), + column("json", "jsonb", Scalar::Jsonb), + Column { + api_name: "maybe".to_string(), + db_name: "maybe".to_string(), + pg_type: "text".to_string(), + pg_type_schema: "pg_catalog".to_string(), + scalar: Scalar::String, + is_array: false, + nullable: true, + description: None, + }, + Column { + api_name: "status".to_string(), + db_name: "status".to_string(), + pg_type: "accounttype".to_string(), + pg_type_schema: "tenant".to_string(), + scalar: Scalar::PgEnum, + is_array: false, + nullable: false, + description: None, + }, + ], + primary_key: vec!["id".to_string()], + object_relationships: vec![crate::serve::model::ObjectRelationship { + name: "self_rel".to_string(), + local_db_column: "id".to_string(), + remote_table: "User".to_string(), + }], + array_relationships: vec![], + admin_only: false, + public_aggregations: false, + }], + pg_schema: "tenant".to_string(), + response_limit: None, + } + } + + /// Plans a request the way the HTTP path does, including the lossy + /// variable-number rewrite of the raw variables text. + fn plan_with_transport( + query: &str, + variables: Option<&str>, + transport: Transport, + ) -> GResult { + let model = test_model(); + let schema = RoleSchema { + registry: schema_build::build(&model, Role::Admin), + role: Role::Admin, + }; + let (variables, variable_number_originals) = match variables { + Some(text) => match json_numbers::rewrite_lossy_numbers(text) { + Some((rewritten, originals)) => ( + Some(serde_json::from_str::(&rewritten).unwrap()), + originals, + ), + None => (Some(serde_json::from_str(text).unwrap()), HashMap::new()), + }, + None => (None, HashMap::new()), + }; + let request = GraphQLRequest { + query: Some(query.to_string()), + variables, + operation_name: None, + variable_number_originals, + }; + plan_request(&model, &schema, &request, transport) + } + + fn plan(query: &str, variables: Option<&str>) -> GResult { + plan_with_transport(query, variables, Transport::Http) + } + + /// The SQL text of a single `big: {_eq: ...}` comparison. + fn eq_sql_text(op: ir::Operation) -> String { + let Some(ir::RootField::Table(root)) = op.root_fields.into_iter().next() else { + panic!("expected a table root"); + }; + let ir::TableRootKind::Many { args, .. } = root.kind else { + panic!("expected a many root"); + }; + let Some(ir::BoolExp::Compare { + op: ir::CompareOp::Eq(v), + .. + }) = args.where_ + else { + panic!("expected a single _eq comparison"); + }; + v.text.unwrap() + } + + fn fragment_chain(count: usize, spreads_per_fragment: usize) -> String { + let mut q = String::from("query { User { ...f0 } } "); + for i in 0..count { + q.push_str(&format!("fragment f{i} on User {{ ")); + if i + 1 < count { + for _ in 0..spreads_per_fragment { + q.push_str(&format!("...f{} ", i + 1)); + } + } else { + q.push_str("id "); + } + q.push('}'); + q.push(' '); + } + q + } + + #[test] + fn double_spread_fragment_chain_small_succeeds() { + assert!(plan(&fragment_chain(10, 2), None).is_ok()); + } + + #[test] + fn double_spread_fragment_chain_large_hits_selection_budget() { + // 2^40 naive expansions: must fail fast with the budget error + // instead of hanging or exhausting memory. + let err = plan(&fragment_chain(40, 2), None).unwrap_err(); + assert_eq!( + err.message, + "the selection set exceeds the maximum of 50000 selections after fragment expansion" + ); + } + + #[test] + fn long_single_spread_fragment_chain_hits_depth_limit() { + // 100k chained fragments would recurse 100k frames in the prepass + // without the frame cap. + let err = plan(&fragment_chain(100_000, 1), None).unwrap_err(); + assert_eq!( + err.message, + "the query exceeds the maximum allowed nesting depth of 100" + ); + } + + fn nested_not_query(n: usize) -> String { + let mut q = String::from("{ User(where: "); + for _ in 0..n { + q.push_str("{_not: "); + } + q.push_str("{id: {_eq: \"1\"}}"); + for _ in 0..n { + q.push('}'); + } + q.push_str(") { id } }"); + q + } + + #[test] + fn deep_valid_documents_pass() { + // graphql_parser itself rejects nesting much beyond ~46 input-object + // levels, so the deepest end-to-end-plannable documents sit well + // under the 100 limit; the exact-100 boundary is pinned on the + // pre-parse scan below. + assert!(plan(&nested_not_query(40), None).is_ok()); + let mut q = String::from("{ User "); + for _ in 0..40 { + q.push_str("{ self_rel "); + } + q.push_str("{ id }"); + for _ in 0..40 { + q.push('}'); + } + q.push('}'); + assert!(plan(&q, None).is_ok()); + } + + #[test] + fn prescan_depth_boundary() { + let at_limit = nested_not_query(96); // max bracket depth exactly 100 + let over = nested_not_query(97); + let over_message = match prescan(&over) { + Err(e) => e.message, + Ok(_) => panic!("expected a depth error"), + }; + assert_eq!( + (prescan(&at_limit).is_ok(), over_message), + ( + true, + "the query exceeds the maximum allowed nesting depth of 100".to_string(), + ) + ); + } + + #[test] + fn nesting_depth_over_limit_errors() { + for n in [97, 200, 100_000] { + let err = plan(&nested_not_query(n), None).unwrap_err(); + assert_eq!( + (n, err.message.as_str(), err.code), + ( + n, + "the query exceeds the maximum allowed nesting depth of 100", + CODE_VALIDATION_FAILED + ) + ); + } + } + + #[test] + fn fragment_expansion_depth_over_limit_errors() { + // Each fragment nests 50 selection levels lexically (fine), but + // spreading one inside the other expands past 100. + let mut q = String::from("query { User { ...f0 } } "); + for i in 0..3 { + q.push_str(&format!("fragment f{i} on User {{ ")); + let mut depth = 0; + for _ in 0..49 { + q.push_str("u { "); + depth += 1; + } + if i < 2 { + q.push_str(&format!("...f{} ", i + 1)); + } else { + q.push_str("id "); + } + for _ in 0..depth { + q.push('}'); + } + q.push_str("} "); + } + let err = plan(&q, None).unwrap_err(); + assert_eq!( + err.message, + "the query exceeds the maximum allowed nesting depth of 100" + ); + } + + #[test] + fn fragment_cycle_error_is_preserved() { + let q = "query { User { ...a } } \ + fragment a on User { ...b } fragment b on User { ...a }"; + let err = plan(q, None).unwrap_err(); + assert_eq!( + err.message, + "the fragment definition(s) a and b form a cycle" + ); + } + + #[test] + fn big_integer_variable_reaches_sql_losslessly() { + let op = plan( + "query($v: numeric) { User(where: {big: {_eq: $v}}) { id } }", + Some(r#"{"v": 99999999999999999999999}"#), + ) + .unwrap(); + assert_eq!(eq_sql_text(op), "99999999999999999999999"); + } + + #[test] + fn high_precision_decimal_variable_reaches_sql_losslessly() { + let op = plan( + "query($v: numeric) { User(where: {big: {_eq: $v}}) { id } }", + Some(r#"{"v": 1.00000000000000000000001}"#), + ) + .unwrap(); + assert_eq!(eq_sql_text(op), "1.00000000000000000000001"); + } + + #[test] + fn numeric_float_literals_reach_sql_losslessly() { + for literal in ["1.00000000000000000001", "1e400"] { + let op = plan( + &format!("{{ User(where: {{big: {{_eq: {literal}}}}}) {{ id }} }}"), + None, + ) + .unwrap(); + assert_eq!(eq_sql_text(op), literal); + } + } + + #[test] + fn overflowing_float_variable_is_rejected_before_sql() { + let err = plan( + "query($v: float8!) { User(where: {floating: {_eq: $v}}) { id } }", + Some(r#"{"v": 1e400}"#), + ) + .unwrap_err(); + assert_eq!( + (err.message.as_str(), err.code), + ( + "The value 1.0e400 lies outside the bounds. Is it overflowing the float bounds?", + CODE_PARSE_FAILED, + ) + ); + } + + #[test] + fn large_json_variable_numbers_reach_sql_losslessly() { + let op = plan( + "query($v: jsonb) { User(where: {json: {_contains: $v}}) { id } }", + Some(r#"{"v": {"n": 99999999999999999999999}}"#), + ) + .unwrap(); + let Some(ir::RootField::Table(root)) = op.root_fields.into_iter().next() else { + panic!("expected a table root"); + }; + let ir::TableRootKind::Many { args, .. } = root.kind else { + panic!("expected a many root"); + }; + let Some(ir::BoolExp::Compare { + op: ir::CompareOp::Contains(value), + .. + }) = args.where_ + else { + panic!("expected a jsonb _contains comparison"); + }; + assert_eq!( + value.text.as_deref(), + Some(r#"{"n":99999999999999999999999}"#) + ); + } + + #[test] + fn client_cannot_spoof_variable_number_originals() { + let err = plan( + "query($v: numeric) { User(where: {big: {_eq: $v}}) { id } }", + Some( + r#"{"v": 1.5, "\u0001variable number originals": {"4609434218613702656": "999999999999999999"}}"#, + ), + ) + .unwrap_err(); + assert_eq!(err.code, CODE_VALIDATION_FAILED); + assert!( + err.message + .contains("unexpected variables in variableValues"), + "client-owned variables must not be trusted as decoder metadata: {}", + err.message + ); + } + + #[test] + fn websocket_rejects_non_object_variables() { + let model = test_model(); + let schema = RoleSchema { + registry: schema_build::build(&model, Role::Admin), + role: Role::Admin, + }; + let request = GraphQLRequest { + query: Some("{ User { id } }".to_string()), + variables: Some(serde_json::json!([])), + operation_name: None, + variable_number_originals: HashMap::new(), + }; + let err = plan_request(&model, &schema, &request, Transport::Ws).unwrap_err(); + assert_eq!( + (err.message.as_str(), err.path.as_str(), err.code), + ( + "parsing HashMap failed, expected Object, but encountered Array", + "$.variables", + CODE_PARSE_FAILED, + ) + ); + } + + #[test] + fn explicit_null_stream_cursor_is_a_bounded_position() { + let op = plan_with_transport( + "subscription { User_stream(batch_size: 2, cursor: {initial_value: {maybe: null}, ordering: DESC}) { id } }", + None, + Transport::Ws, + ) + .unwrap(); + let Some(ir::RootField::Table(root)) = op.root_fields.first() else { + panic!("expected a table root"); + }; + let ir::TableRootKind::Stream { cursor, .. } = &root.kind else { + panic!("expected a stream root"); + }; + assert_eq!(cursor.len(), 1); + let initial = cursor[0] + .initial_value + .as_ref() + .expect("explicit null must not become an unbounded cursor"); + assert_eq!( + (initial.text.as_deref(), initial.cast.as_str()), + (None, "text") + ); + } + + #[test] + fn custom_enum_sql_cast_is_schema_qualified() { + let op = plan(r#"{ User(where: {status: {_eq: "ACTIVE"}}) { id } }"#, None).unwrap(); + let Some(ir::RootField::Table(root)) = op.root_fields.first() else { + panic!("expected a table root"); + }; + let compiled = crate::serve::exec::sql::compile_root_full("tenant", root); + assert!( + compiled.sql.contains("::\"tenant\".\"accounttype\""), + "custom enum casts must resolve outside the default search_path: {}", + compiled.sql + ); + } + + #[test] + fn empty_custom_enum_in_casts_are_schema_qualified() { + for predicate in ["_in", "_nin"] { + let op = plan( + &format!(r#"{{ User(where: {{status: {{{predicate}: []}}}}) {{ id }} }}"#), + None, + ) + .unwrap(); + let Some(ir::RootField::Table(root)) = op.root_fields.first() else { + panic!("expected a table root"); + }; + let compiled = crate::serve::exec::sql::compile_root_full("tenant", root); + assert!( + compiled.sql.contains("::\"tenant\".\"accounttype\"[]"), + "empty {predicate} must retain the custom enum namespace: {}", + compiled.sql + ); + } + } + + #[test] + fn ordinary_number_variables_are_unchanged() { + for (vars, expected) in [ + (r#"{"v": 1.5}"#, "1.5"), + (r#"{"v": 42}"#, "42"), + (r#"{"v": 1e2}"#, "100"), + (r#"{"v": -7}"#, "-7"), + ] { + let op = plan( + "query($v: numeric) { User(where: {big: {_eq: $v}}) { id } }", + Some(vars), + ) + .unwrap(); + assert_eq!((vars, eq_sql_text(op).as_str()), (vars, expected)); + } + } + + #[test] + fn unexpected_variables_still_reported() { + let err = plan( + "query { User { id } }", + Some(r#"{"v": 99999999999999999999999}"#), + ) + .unwrap_err(); + assert_eq!(err.message, "unexpected variables in variableValues: v"); + } +} diff --git a/packages/cli/src/serve/exec/validate/prescan.rs b/packages/cli/src/serve/exec/validate/prescan.rs new file mode 100644 index 0000000000..84a4c49ee4 --- /dev/null +++ b/packages/cli/src/serve/exec/validate/prescan.rs @@ -0,0 +1,452 @@ +use super::coerce::parse_decimal; +use super::{depth_error, invalid_query, GResult, MAX_DEPTH}; +use std::collections::{HashMap, HashSet}; +use std::fmt::Write as _; + +// --------------------------------------------------------------------------- +// Lexical pre-scan +// --------------------------------------------------------------------------- +// +// graphql-parser cannot represent three things Hasura handles at the lexer +// level: duplicate argument names, duplicate keys in input-object literals +// (both "not a valid graphql query" in Hasura, while graphql-parser silently +// collapses them into a BTreeMap), and int literals beyond i64 (Hasura keeps +// arbitrary precision, graphql-parser fails the whole parse). This token +// scan rejects the duplicates and rewrites oversized int literals to unused +// sentinel i64 values, remembering the original digits. + +pub(super) struct Prescan { + pub(super) rewritten: String, + pub(super) int_originals: HashMap, + /// All float literals that cannot round-trip through f64, keyed by the + /// unique finite sentinel substituted into the parser input. + pub(super) float_originals: HashMap, + /// f64-overflowing float literals were rewritten to per-occurrence + /// finite sentinel values before parsing; this maps each sentinel's bit + /// pattern back to the original digits. Keyed per occurrence (like + /// `int_originals`) rather than merely by sign, so two distinct + /// out-of-range float literals in the same query each report their own + /// text instead of collapsing to whichever one happened to come first. + pub(super) inf_float_originals: HashMap, +} + +#[derive(Clone, Copy, PartialEq)] +enum TokKind { + Name, + Int, + Float, + Str, + Punct(char), +} + +struct Tok<'a> { + kind: TokKind, + text: &'a str, + start: usize, + end: usize, +} + +fn tokenize(src: &str) -> Result>, ()> { + let bytes = src.as_bytes(); + let mut toks = Vec::new(); + let mut i = 0; + while i < bytes.len() { + let c = bytes[i]; + match c { + b' ' | b'\t' | b'\r' | b'\n' | b',' => i += 1, + b'#' => { + while i < bytes.len() && bytes[i] != b'\n' { + i += 1; + } + } + b'"' => { + let start = i; + if bytes[i..].starts_with(b"\"\"\"") { + i += 3; + loop { + if i >= bytes.len() { + return Err(()); + } + if bytes[i] == b'\\' { + i += 2; + } else if bytes[i..].starts_with(b"\"\"\"") { + i += 3; + break; + } else { + i += 1; + } + } + } else { + i += 1; + loop { + if i >= bytes.len() { + return Err(()); + } + match bytes[i] { + b'\\' => i += 2, + b'"' => { + i += 1; + break; + } + b'\n' => return Err(()), + _ => i += 1, + } + } + } + toks.push(Tok { + kind: TokKind::Str, + text: &src[start..i], + start, + end: i, + }); + } + b'-' | b'0'..=b'9' => { + let start = i; + if c == b'-' { + i += 1; + } + while i < bytes.len() && bytes[i].is_ascii_digit() { + i += 1; + } + let mut is_float = false; + if i < bytes.len() && bytes[i] == b'.' { + is_float = true; + i += 1; + while i < bytes.len() && bytes[i].is_ascii_digit() { + i += 1; + } + } + if i < bytes.len() && (bytes[i] == b'e' || bytes[i] == b'E') { + is_float = true; + i += 1; + if i < bytes.len() && (bytes[i] == b'+' || bytes[i] == b'-') { + i += 1; + } + while i < bytes.len() && bytes[i].is_ascii_digit() { + i += 1; + } + } + toks.push(Tok { + kind: if is_float { + TokKind::Float + } else { + TokKind::Int + }, + text: &src[start..i], + start, + end: i, + }); + } + b'_' | b'a'..=b'z' | b'A'..=b'Z' => { + let start = i; + while i < bytes.len() && (bytes[i] == b'_' || bytes[i].is_ascii_alphanumeric()) { + i += 1; + } + toks.push(Tok { + kind: TokKind::Name, + text: &src[start..i], + start, + end: i, + }); + } + _ => { + // Multi-byte UTF-8 or punctuation; treat one char at a time. + let ch_len = src[i..].chars().next().map(|c| c.len_utf8()).unwrap_or(1); + toks.push(Tok { + kind: TokKind::Punct(c as char), + text: &src[i..i + ch_len], + start: i, + end: i + ch_len, + }); + i += ch_len; + } + } + } + Ok(toks) +} + +pub(super) fn prescan(src: &str) -> GResult { + let toks = tokenize(src).map_err(|_| invalid_query())?; + + // Nesting depth must be bounded before graphql_parser runs: its + // recursive-descent parser overflows the stack (aborting the process) + // on deeply nested documents, so this cannot wait for the AST. + let mut depth: usize = 0; + for t in &toks { + match t.kind { + TokKind::Punct('(') | TokKind::Punct('[') | TokKind::Punct('{') => { + depth += 1; + if depth > MAX_DEPTH { + return Err(depth_error()); + } + } + TokKind::Punct(')') | TokKind::Punct(']') | TokKind::Punct('}') => { + depth = depth.saturating_sub(1); + } + _ => {} + } + } + + // Duplicate argument names / duplicate input-object keys. Inside + // argument parentheses every `{` opens an object literal (selection + // sets cannot occur there), so key tracking only runs at paren depth + // > 0. Names preceded by `$` are variable definitions, not keys. + enum Scope { + Args(HashSet), + Object(HashSet), + List, + } + let mut scopes: Vec = Vec::new(); + for (idx, t) in toks.iter().enumerate() { + match t.kind { + TokKind::Punct('(') => scopes.push(Scope::Args(HashSet::new())), + TokKind::Punct(')') => { + while let Some(s) = scopes.pop() { + if matches!(s, Scope::Args(_)) { + break; + } + } + } + TokKind::Punct('{') if !scopes.is_empty() => scopes.push(Scope::Object(HashSet::new())), + TokKind::Punct('}') => { + if matches!(scopes.last(), Some(Scope::Object(_))) { + scopes.pop(); + } + } + TokKind::Punct('[') if !scopes.is_empty() => scopes.push(Scope::List), + TokKind::Punct(']') => { + if matches!(scopes.last(), Some(Scope::List)) { + scopes.pop(); + } + } + TokKind::Name => { + let followed_by_colon = + matches!(toks.get(idx + 1), Some(n) if n.kind == TokKind::Punct(':')); + let preceded_by_dollar = idx > 0 && toks[idx - 1].kind == TokKind::Punct('$'); + if followed_by_colon && !preceded_by_dollar { + match scopes.last_mut() { + Some(Scope::Args(keys)) | Some(Scope::Object(keys)) => { + if !keys.insert(t.text.to_string()) { + return Err(invalid_query()); + } + } + _ => {} + } + } + } + _ => {} + } + } + + // Oversized int literals and f64-overflowing float literals both get + // rewritten to unique sentinel literals so the parsed AST carries a + // value we can map back to the original text for error display. + enum Rewrite { + Int, + Float { overflow: bool }, + } + let mut int_originals: HashMap = HashMap::new(); + let mut float_originals: HashMap = HashMap::new(); + let mut inf_float_originals: HashMap = HashMap::new(); + let mut taken_int_values: HashSet = HashSet::new(); + let mut taken_float_values: HashSet = HashSet::new(); + let mut rewrites: Vec<(usize, Rewrite)> = Vec::new(); + for (idx, t) in toks.iter().enumerate() { + match t.kind { + TokKind::Int => match t.text.parse::() { + Ok(n) => { + taken_int_values.insert(n); + } + Err(_) => rewrites.push((idx, Rewrite::Int)), + }, + TokKind::Float => { + if let Ok(f) = t.text.parse::() { + let overflow = !f.is_finite(); + let roundtrips = + !overflow && parse_decimal(t.text) == parse_decimal(&format!("{f}")); + if !roundtrips { + rewrites.push((idx, Rewrite::Float { overflow })); + } else { + taken_float_values.insert(f.to_bits()); + } + } + } + _ => {} + } + } + + let rewritten = if rewrites.is_empty() { + src.to_string() + } else { + let mut magic_int = i64::MAX; + // Each occurrence steps one f64 ULP closer to zero from MAX/MIN, so + // every rewritten literal gets its own exact, round-trippable + // sentinel value instead of all collapsing to the same infinity. + let mut magic_pos_float = f64::MAX; + let mut magic_neg_float = f64::MIN; + let mut out = String::with_capacity(src.len()); + let mut pos = 0; + for (idx, kind) in rewrites { + let t = &toks[idx]; + out.push_str(&src[pos..t.start]); + match kind { + Rewrite::Int => { + while taken_int_values.contains(&magic_int) + || int_originals.contains_key(&magic_int) + { + magic_int -= 1; + } + int_originals.insert(magic_int, t.text.to_string()); + out.push_str(&magic_int.to_string()); + } + Rewrite::Float { overflow } => { + let magic = if t.text.starts_with('-') { + &mut magic_neg_float + } else { + &mut magic_pos_float + }; + while taken_float_values.contains(&magic.to_bits()) + || float_originals.contains_key(&magic.to_bits()) + { + *magic = f64::from_bits(magic.to_bits() - 1); + } + let bits = magic.to_bits(); + float_originals.insert(bits, t.text.to_string()); + if overflow { + inf_float_originals.insert(bits, t.text.to_string()); + } + let _ = write!(out, "{magic:e}"); + } + } + pos = t.end; + } + out.push_str(&src[pos..]); + out + }; + + Ok(Prescan { + rewritten, + int_originals, + float_originals, + inf_float_originals, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use graphql_parser::query as q; + + #[test] + fn prescan_duplicates_and_rewrites() { + assert!(prescan("{ User(limit: 1, limit: 2) { id } }").is_err()); + assert!(prescan("{ User(where: {id: {_eq: \"a\", _eq: \"b\"}}) { id } }").is_err()); + assert!(prescan("query ($l: Int, $l: Int) { User(limit: $l) { id } }").is_ok()); + assert!(prescan("{ a: User { id } a: User { id } }").is_ok()); + assert!(prescan("{ User(where: {a: {_eq: 1}, b: {_eq: 1}}) { id } }").is_ok()); + // String contents must not confuse scope tracking. + assert!(prescan("{ User(where: {id: {_eq: \"({[\"}}) { id } }").is_ok()); + + let scan = prescan("{ User(limit: 9223372036854775808) { id } }").unwrap(); + let (magic, orig) = scan.int_originals.iter().next().unwrap(); + assert_eq!( + ( + scan.int_originals.len(), + orig.as_str(), + scan.rewritten.contains(&magic.to_string()), + q::parse_query::(&scan.rewritten).is_ok(), + ), + (1, "9223372036854775808", true, true) + ); + + let scan = prescan("{ E(where: {f: {_lt: 1e400}}) { id } }").unwrap(); + let (bits, orig) = scan.inf_float_originals.iter().next().unwrap(); + assert_eq!( + ( + scan.inf_float_originals.len(), + orig.as_str(), + scan.rewritten + .contains(&format!("{:e}", f64::from_bits(*bits))), + q::parse_query::(&scan.rewritten).is_ok(), + ), + (1, "1e400", true, true) + ); + + // Two distinct literals overflowing to the same-signed infinity must + // each keep their own original text (not collapse to one entry). + let scan = + prescan("{ E(where: {_and: [{f: {_lt: 1e400}}, {g: {_lt: 9e999}}]}) { id } }").unwrap(); + let mut origs: Vec<&String> = scan.inf_float_originals.values().collect(); + origs.sort(); + assert_eq!( + (scan.inf_float_originals.len(), origs), + (2, vec![&"1e400".to_string(), &"9e999".to_string()]) + ); + } +} + +#[cfg(test)] +mod roundtrip_check { + use super::*; + use graphql_parser::query as q; + + #[test] + fn inf_float_sentinel_roundtrips_bit_exact_through_the_real_parser() { + let scan = prescan( + "{ E(where: {_and: [{f: {_lt: 1e400}}, {g: {_lt: 9e999}}, {h: {_lt: -1e500}}]}) { id } }", + ) + .unwrap(); + assert_eq!(scan.inf_float_originals.len(), 3); + + let doc = q::parse_query::(&scan.rewritten).expect("rewritten text parses"); + // Walk the AST to find every Float literal value actually produced + // by the real parser, and check each one's bit pattern is a key in + // inf_float_originals (i.e. round-tripped exactly). + let mut found_floats = Vec::new(); + fn walk_value(v: &q::Value, out: &mut Vec) { + match v { + q::Value::Float(f) => out.push(*f), + q::Value::Object(m) => { + for v in m.values() { + walk_value(v, out); + } + } + q::Value::List(items) => { + for v in items { + walk_value(v, out); + } + } + _ => {} + } + } + fn selection_set<'a>( + op: &'a q::OperationDefinition<'a, String>, + ) -> &'a q::SelectionSet<'a, String> { + match op { + q::OperationDefinition::SelectionSet(s) => s, + q::OperationDefinition::Query(q) => &q.selection_set, + q::OperationDefinition::Mutation(m) => &m.selection_set, + q::OperationDefinition::Subscription(s) => &s.selection_set, + } + } + for def in &doc.definitions { + if let q::Definition::Operation(op) = def { + for field_sel in &selection_set(op).items { + if let q::Selection::Field(f) = field_sel { + for (_, v) in &f.arguments { + walk_value(v, &mut found_floats); + } + } + } + } + } + assert_eq!(found_floats.len(), 3); + for f in found_floats { + assert!( + scan.inf_float_originals.contains_key(&f.to_bits()), + "parsed sentinel {f} (bits {:x}) not found in inf_float_originals -- text/reparse round trip lost precision", + f.to_bits() + ); + } + } +} diff --git a/packages/cli/src/serve/exec/validate/selection.rs b/packages/cli/src/serve/exec/validate/selection.rs new file mode 100644 index 0000000000..ebd63fb73f --- /dev/null +++ b/packages/cli/src/serve/exec/validate/selection.rs @@ -0,0 +1,247 @@ +use super::coerce::coerce_bool_strict; +use super::{q, verr, ADirective, ASelSet, AValue, Ctx, GResult, TypeRef}; +use std::collections::{BTreeMap, HashMap}; + +// --------------------------------------------------------------------------- +// Selection walking: directives, fragments, field merging +// --------------------------------------------------------------------------- + +pub(super) struct Flat<'a> { + pub(super) key: String, + pub(super) name: &'a str, + pub(super) args: &'a [(String, AValue)], + pub(super) sel_sets: Vec<&'a ASelSet>, + pub(super) had_selection: bool, +} + +/// Evaluates @include/@skip (with variables) on a selection item. Returns +/// false when the item must be dropped. Unknown/duplicate directives and +/// bad `if` arguments error with paths anchored at the enclosing +/// selection set, matching Hasura. +fn eval_directives<'a>(ctx: &'a Ctx<'a>, dirs: &'a [ADirective], sel_path: &str) -> GResult { + if dirs.is_empty() { + return Ok(true); + } + let mut seen: Vec<&str> = Vec::new(); + let mut dups: Vec<&str> = Vec::new(); + for d in dirs { + let name = d.name.as_str(); + if seen.contains(&name) { + if !dups.contains(&name) { + dups.push(name); + } + } else { + seen.push(name); + } + } + if !dups.is_empty() { + let list = dups + .iter() + .map(|n| format!("'{n}'")) + .collect::>() + .join(", "); + return Err(verr( + sel_path, + format!("the following directives are used more than once: [{list}]"), + )); + } + + let mut include = true; + for d in dirs { + let name = d.name.as_str(); + match name { + "include" | "skip" => { + for (arg, _) in &d.arguments { + if arg != "if" { + return Err(verr( + format!("{sel_path}.{name}"), + format!("'{name}' has no argument named '{arg}'"), + )); + } + } + let if_path = format!("{sel_path}.{name}.args.if"); + let Some((_, raw)) = d.arguments.iter().find(|(a, _)| a == "if") else { + return Err(verr(if_path, "missing required field 'if'")); + }; + let loc_ty = TypeRef::non_null(TypeRef::named("Boolean")); + let v = ctx.resolve(raw, &loc_ty, false, &if_path)?; + let cond = coerce_bool_strict(v, &if_path)?; + match name { + "include" if !cond => include = false, + "skip" if cond => include = false, + _ => {} + } + } + "cached" => { + return Err(verr( + sel_path, + "directive 'cached' is not allowed on a field", + )); + } + other => { + return Err(verr( + sel_path, + format!("directive '{other}' is not defined in the schema"), + )); + } + } + } + Ok(include) +} + +/// Fragments are re-expanded at every spread site during flattening, so a +/// chain of fragments each spread twice grows exponentially; this budget on +/// processed selection items turns that into a graceful validation error. +const MAX_SELECTIONS: usize = 50_000; + +pub(super) fn collect_fields<'a>( + ctx: &'a Ctx<'a>, + type_name: &str, + sets: &[&'a ASelSet], + sel_path: &str, +) -> GResult>> { + let mut out: Vec> = Vec::new(); + let mut index: HashMap = HashMap::new(); + let mut budget = MAX_SELECTIONS; + for set in sets { + collect_into( + ctx, + type_name, + set, + sel_path, + &mut out, + &mut index, + &mut budget, + )?; + } + Ok(out) +} + +#[allow(clippy::too_many_arguments)] +fn collect_into<'a>( + ctx: &'a Ctx<'a>, + type_name: &str, + set: &'a ASelSet, + sel_path: &str, + out: &mut Vec>, + index: &mut HashMap, + budget: &mut usize, +) -> GResult<()> { + for item in &set.items { + if *budget == 0 { + return Err(verr( + sel_path, + format!( + "the selection set exceeds the maximum of {MAX_SELECTIONS} selections after fragment expansion" + ), + )); + } + *budget -= 1; + match item { + q::Selection::Field(f) => { + if !eval_directives(ctx, &f.directives, sel_path)? { + continue; + } + let key = f.alias.clone().unwrap_or_else(|| f.name.clone()); + match index.get(&key) { + Some(&i) => { + let existing = &mut out[i]; + if existing.name != f.name { + return Err(verr( + sel_path, + format!( + "selection of both '{}' and '{}' specify the same response name, '{}'", + existing.name, f.name, key + ), + )); + } + if !args_equal(existing.args, &f.arguments) { + return Err(verr( + sel_path, + format!( + "inconsistent arguments between multiple selections of field '{}'", + f.name + ), + )); + } + if !f.selection_set.items.is_empty() { + existing.sel_sets.push(&f.selection_set); + existing.had_selection = true; + } + } + None => { + index.insert(key.clone(), out.len()); + let had_selection = !f.selection_set.items.is_empty(); + out.push(Flat { + key, + name: &f.name, + args: &f.arguments, + sel_sets: if had_selection { + vec![&f.selection_set] + } else { + vec![] + }, + had_selection, + }); + } + } + } + q::Selection::FragmentSpread(spread) => { + if !eval_directives(ctx, &spread.directives, sel_path)? { + continue; + } + let Some(frag) = ctx.fragments.get(spread.fragment_name.as_str()) else { + return Err(verr( + sel_path, + format!( + "reference to undefined fragment \"{}\"", + spread.fragment_name + ), + )); + }; + // Non-matching (or unknown) type conditions drop the + // fragment silently, as Hasura does. + let q::TypeCondition::On(cond) = &frag.type_condition; + if cond == type_name { + collect_into( + ctx, + type_name, + &frag.selection_set, + sel_path, + out, + index, + budget, + )?; + } + } + q::Selection::InlineFragment(inline) => { + if !eval_directives(ctx, &inline.directives, sel_path)? { + continue; + } + let matches = match &inline.type_condition { + None => true, + Some(q::TypeCondition::On(cond)) => cond == type_name, + }; + if matches { + collect_into( + ctx, + type_name, + &inline.selection_set, + sel_path, + out, + index, + budget, + )?; + } + } + } + } + Ok(()) +} + +fn args_equal(a: &[(String, AValue)], b: &[(String, AValue)]) -> bool { + fn to_map(args: &[(String, AValue)]) -> BTreeMap<&str, &AValue> { + args.iter().map(|(k, v)| (k.as_str(), v)).collect() + } + to_map(a) == to_map(b) +} diff --git a/packages/cli/src/serve/exec/validate/variables.rs b/packages/cli/src/serve/exec/validate/variables.rs new file mode 100644 index 0000000000..456b9e415a --- /dev/null +++ b/packages/cli/src/serve/exec/validate/variables.rs @@ -0,0 +1,148 @@ +use super::{ + perr, q, verr, ADirective, ASelSet, AType, AValue, AVarDef, Ctx, GResult, Json, NULL_LIT, +}; +use std::collections::{HashMap, HashSet}; + +// --------------------------------------------------------------------------- +// Variables +// --------------------------------------------------------------------------- + +pub(super) enum VarValue<'a> { + Json(&'a Json), + Lit(&'a AValue), +} + +pub(super) struct VarInfo<'a> { + pub(super) ty: &'a AType, + pub(super) default: Option<&'a AValue>, + pub(super) value: VarValue<'a>, +} + +pub(super) fn atype_display(t: &AType) -> String { + match t { + q::Type::NamedType(n) => n.clone(), + q::Type::ListType(inner) => format!("[{}]", atype_display(inner)), + q::Type::NonNullType(inner) => format!("{}!", atype_display(inner)), + } +} + +pub(super) fn atype_is_non_null(t: &AType) -> bool { + matches!(t, q::Type::NonNullType(_)) +} + +pub(super) fn build_variables<'a>( + defs: &'a [AVarDef], + provided: Option<&'a serde_json::Map>, +) -> GResult>> { + let mut vars: HashMap<&str, VarInfo> = HashMap::new(); + for def in defs { + if vars.contains_key(def.name.as_str()) { + return Err(perr( + "$", + format!("multiple definitions for variable \"{}\"", def.name), + )); + } + let value = match provided.and_then(|m| m.get(def.name.as_str())) { + Some(json) => { + if json.is_null() && atype_is_non_null(&def.var_type) { + return Err(verr( + "$", + format!( + "null value found for non-nullable type: \"{}\"", + atype_display(&def.var_type) + ), + )); + } + VarValue::Json(json) + } + None => match &def.default_value { + Some(d) => VarValue::Lit(d), + None => { + if atype_is_non_null(&def.var_type) { + return Err(verr( + "$", + format!( + "expecting a value for non-nullable variable: \"{}\"", + def.name + ), + )); + } + VarValue::Lit(&NULL_LIT) + } + }, + }; + vars.insert( + def.name.as_str(), + VarInfo { + ty: &def.var_type, + default: def.default_value.as_ref(), + value, + }, + ); + } + Ok(vars) +} + +pub(super) fn variable_prepass<'a>(ctx: &Ctx<'a>, set: &'a ASelSet) -> GResult<()> { + let mut visited: HashSet<&'a str> = HashSet::new(); + walk(ctx, set, &mut visited) +} + +fn walk<'a>(ctx: &Ctx<'a>, set: &'a ASelSet, visited: &mut HashSet<&'a str>) -> GResult<()> { + fn mark_value<'a>(ctx: &Ctx<'a>, v: &'a AValue) -> GResult<()> { + match v { + q::Value::Variable(name) => { + if !ctx.vars.contains_key(name.as_str()) { + return Err(verr("$", format!("unbound variable \"{name}\""))); + } + ctx.mark_used(name); + } + q::Value::List(items) => { + for item in items { + mark_value(ctx, item)?; + } + } + q::Value::Object(map) => { + for value in map.values() { + mark_value(ctx, value)?; + } + } + _ => {} + } + Ok(()) + } + fn mark_directives<'a>(ctx: &Ctx<'a>, dirs: &'a [ADirective]) -> GResult<()> { + for d in dirs { + for (_, v) in &d.arguments { + mark_value(ctx, v)?; + } + } + Ok(()) + } + for item in &set.items { + match item { + q::Selection::Field(f) => { + for (_, v) in &f.arguments { + mark_value(ctx, v)?; + } + mark_directives(ctx, &f.directives)?; + walk(ctx, &f.selection_set, visited)?; + } + q::Selection::FragmentSpread(spread) => { + mark_directives(ctx, &spread.directives)?; + // A fragment already fully walked cannot mark anything new; + // skipping it also keeps a chain of double spreads linear. + if visited.insert(spread.fragment_name.as_str()) { + if let Some(frag) = ctx.fragments.get(spread.fragment_name.as_str()) { + walk(ctx, &frag.selection_set, visited)?; + } + } + } + q::Selection::InlineFragment(inline) => { + mark_directives(ctx, &inline.directives)?; + walk(ctx, &inline.selection_set, visited)?; + } + } + } + Ok(()) +} diff --git a/packages/cli/src/serve/gql/introspection.rs b/packages/cli/src/serve/gql/introspection.rs new file mode 100644 index 0000000000..58760d7999 --- /dev/null +++ b/packages/cli/src/serve/gql/introspection.rs @@ -0,0 +1,672 @@ +//! Resolves `__schema` / `__type` selections against the registry, +//! producing JSON text that matches Hasura's introspection responses +//! byte-for-byte (field order follows the selection set; type lists are +//! ordered by type name). + +use super::types::{EnumValueDef, FieldDef, InputValueDef, Registry, TypeDef, TypeRef}; +use crate::serve::exec::error::{GResult, GraphQLError}; +use crate::serve::exec::ir::{IntroSelItem, IntroSelection, IntrospectionField}; + +/// Returns the serialized JSON value for the introspection field. +pub fn resolve(registry: &Registry, field: &IntrospectionField) -> GResult { + let mut out = String::with_capacity(256); + match field.field.as_str() { + "__schema" => write_schema(registry, &field.selection, &mut out)?, + "__type" => match field.type_name.as_deref().and_then(|n| registry.get(n)) { + Some(def) => write_type(registry, TypeView::Def(def), &field.selection, &mut out)?, + None => out.push_str("null"), + }, + other => { + return Err(internal(format!( + "unexpected introspection root field '{other}'" + ))) + } + } + Ok(out) +} + +/// Fallback for selections validate.rs should have rejected already. +fn internal(message: String) -> GraphQLError { + GraphQLError::validation("$", message) +} + +fn subsel(item: &IntroSelItem) -> GResult<&IntroSelection> { + item.selection + .as_ref() + .ok_or_else(|| internal(format!("field '{}' requires a selection set", item.field))) +} + +fn write_json_string(out: &mut String, s: &str) { + out.push('"'); + for c in s.chars() { + match c { + '"' => out.push_str("\\\""), + '\\' => out.push_str("\\\\"), + '\n' => out.push_str("\\n"), + '\r' => out.push_str("\\r"), + '\t' => out.push_str("\\t"), + '\u{08}' => out.push_str("\\b"), + '\u{0C}' => out.push_str("\\f"), + c if (c as u32) < 0x20 => { + out.push_str(&format!("\\u{:04x}", c as u32)); + } + c => out.push(c), + } + } + out.push('"'); +} + +fn write_opt_str(out: &mut String, s: Option<&str>) { + match s { + Some(s) => write_json_string(out, s), + None => out.push_str("null"), + } +} + +/// Writes `{ "": , ... }` in selection order. +fn write_object( + sel: &IntroSelection, + out: &mut String, + mut value: impl FnMut(&IntroSelItem, &mut String) -> GResult<()>, +) -> GResult<()> { + out.push('{'); + let mut first = true; + for item in &sel.items { + if !first { + out.push(','); + } + first = false; + write_json_string(out, &item.alias); + out.push(':'); + value(item, out)?; + } + out.push('}'); + Ok(()) +} + +fn write_array( + out: &mut String, + items: impl IntoIterator, + mut value: impl FnMut(T, &mut String) -> GResult<()>, +) -> GResult<()> { + out.push('['); + let mut first = true; + for it in items { + if !first { + out.push(','); + } + first = false; + value(it, out)?; + } + out.push(']'); + Ok(()) +} + +fn write_schema(registry: &Registry, sel: &IntroSelection, out: &mut String) -> GResult<()> { + write_object(sel, out, |item, out| { + match item.field.as_str() { + "__typename" => write_json_string(out, "__Schema"), + "description" => out.push_str("null"), + "queryType" => write_root_type(registry, Some(®istry.query_root), item, out)?, + "mutationType" => { + write_root_type(registry, registry.mutation_root.as_deref(), item, out)? + } + "subscriptionType" => { + write_root_type(registry, Some(®istry.subscription_root), item, out)? + } + "types" => { + let sub = subsel(item)?; + write_array(out, registry.types.values(), |def, out| { + write_type(registry, TypeView::Def(def), sub, out) + })?; + } + "directives" => { + let sub = subsel(item)?; + write_array(out, directives().iter(), |d, out| { + write_directive(registry, d, sub, out) + })?; + } + other => return Err(internal(format!("unexpected field '{other}' on __Schema"))), + } + Ok(()) + }) +} + +fn write_root_type( + registry: &Registry, + name: Option<&str>, + item: &IntroSelItem, + out: &mut String, +) -> GResult<()> { + match name.and_then(|n| registry.get(n)) { + Some(def) => write_type(registry, TypeView::Def(def), subsel(item)?, out), + None => { + out.push_str("null"); + Ok(()) + } + } +} + +/// One step of a type-ref chain: a registry type, or a NonNull/List wrapper +/// whose `ofType` continues the chain. +#[derive(Clone, Copy)] +enum TypeView<'a> { + Def(&'a TypeDef), + NonNull(&'a TypeRef), + List(&'a TypeRef), +} + +fn view_of<'a>(registry: &'a Registry, r: &'a TypeRef) -> Option> { + match r { + TypeRef::Named(n) => registry.get(n).map(TypeView::Def), + TypeRef::NonNull(inner) => Some(TypeView::NonNull(inner)), + TypeRef::List(inner) => Some(TypeView::List(inner)), + } +} + +fn write_type_ref( + registry: &Registry, + r: &TypeRef, + sel: &IntroSelection, + out: &mut String, +) -> GResult<()> { + match view_of(registry, r) { + Some(view) => write_type(registry, view, sel, out), + None => { + out.push_str("null"); + Ok(()) + } + } +} + +fn def_description(def: &TypeDef) -> Option<&str> { + match def { + TypeDef::Scalar { description, .. } + | TypeDef::Object { description, .. } + | TypeDef::InputObject { description, .. } + | TypeDef::Enum { description, .. } => description.as_deref(), + } +} + +fn write_type( + registry: &Registry, + view: TypeView, + sel: &IntroSelection, + out: &mut String, +) -> GResult<()> { + write_object(sel, out, |item, out| { + match item.field.as_str() { + "__typename" => write_json_string(out, "__Type"), + "kind" => { + let kind = match view { + TypeView::Def(TypeDef::Scalar { .. }) => "SCALAR", + TypeView::Def(TypeDef::Object { .. }) => "OBJECT", + TypeView::Def(TypeDef::InputObject { .. }) => "INPUT_OBJECT", + TypeView::Def(TypeDef::Enum { .. }) => "ENUM", + TypeView::NonNull(_) => "NON_NULL", + TypeView::List(_) => "LIST", + }; + write_json_string(out, kind); + } + "name" => match view { + TypeView::Def(def) => write_json_string(out, def.name()), + _ => out.push_str("null"), + }, + "description" => match view { + TypeView::Def(def) => write_opt_str(out, def_description(def)), + _ => out.push_str("null"), + }, + // Nothing in the schema is deprecated, so includeDeprecated has + // no effect on fields/enumValues. + "fields" => match view { + TypeView::Def(TypeDef::Object { fields, .. }) => { + let sub = subsel(item)?; + write_array(out, fields.iter(), |f, out| { + write_field(registry, f, sub, out) + })?; + } + _ => out.push_str("null"), + }, + "inputFields" => match view { + TypeView::Def(TypeDef::InputObject { fields, .. }) => { + let sub = subsel(item)?; + write_array(out, fields.iter(), |f, out| { + write_input_value(registry, f, sub, out) + })?; + } + _ => out.push_str("null"), + }, + "interfaces" => match view { + TypeView::Def(TypeDef::Object { .. }) => out.push_str("[]"), + _ => out.push_str("null"), + }, + "enumValues" => match view { + TypeView::Def(TypeDef::Enum { values, .. }) => { + let sub = subsel(item)?; + write_array(out, values.iter(), |v, out| write_enum_value(v, sub, out))?; + } + _ => out.push_str("null"), + }, + "possibleTypes" => out.push_str("null"), + "ofType" => match view { + TypeView::NonNull(inner) | TypeView::List(inner) => { + write_type_ref(registry, inner, subsel(item)?, out)? + } + TypeView::Def(_) => out.push_str("null"), + }, + other => return Err(internal(format!("unexpected field '{other}' on __Type"))), + } + Ok(()) + }) +} + +fn write_field( + registry: &Registry, + field: &FieldDef, + sel: &IntroSelection, + out: &mut String, +) -> GResult<()> { + write_object(sel, out, |item, out| { + match item.field.as_str() { + "__typename" => write_json_string(out, "__Field"), + "name" => write_json_string(out, &field.name), + "description" => write_opt_str(out, field.description.as_deref()), + "args" => { + let sub = subsel(item)?; + write_array(out, field.args.iter(), |a, out| { + write_input_value(registry, a, sub, out) + })?; + } + "type" => write_type_ref(registry, &field.ty, subsel(item)?, out)?, + "isDeprecated" => out.push_str("false"), + "deprecationReason" => out.push_str("null"), + other => return Err(internal(format!("unexpected field '{other}' on __Field"))), + } + Ok(()) + }) +} + +fn write_input_value( + registry: &Registry, + input: &InputValueDef, + sel: &IntroSelection, + out: &mut String, +) -> GResult<()> { + write_object(sel, out, |item, out| { + match item.field.as_str() { + "__typename" => write_json_string(out, "__InputValue"), + "name" => write_json_string(out, &input.name), + "description" => write_opt_str(out, input.description.as_deref()), + "type" => write_type_ref(registry, &input.ty, subsel(item)?, out)?, + "defaultValue" => write_opt_str(out, input.default_value.as_deref()), + other => { + return Err(internal(format!( + "unexpected field '{other}' on __InputValue" + ))) + } + } + Ok(()) + }) +} + +fn write_enum_value(value: &EnumValueDef, sel: &IntroSelection, out: &mut String) -> GResult<()> { + write_object(sel, out, |item, out| { + match item.field.as_str() { + "__typename" => write_json_string(out, "__EnumValue"), + "name" => write_json_string(out, &value.name), + "description" => write_opt_str(out, value.description.as_deref()), + "isDeprecated" => out.push_str("false"), + "deprecationReason" => out.push_str("null"), + other => { + return Err(internal(format!( + "unexpected field '{other}' on __EnumValue" + ))) + } + } + Ok(()) + }) +} + +struct DirectiveDef { + name: &'static str, + description: &'static str, + locations: &'static [&'static str], + args: Vec, +} + +fn directives() -> Vec { + let if_arg = InputValueDef::new("if", None, TypeRef::non_null(TypeRef::named("Boolean"))); + let ttl = { + let mut arg = InputValueDef::new( + "ttl", + Some("measured in seconds"), + TypeRef::non_null(TypeRef::named("Int")), + ); + arg.default_value = Some("60".to_string()); + arg + }; + let refresh = { + let mut arg = InputValueDef::new( + "refresh", + Some("refresh the cache entry"), + TypeRef::non_null(TypeRef::named("Boolean")), + ); + arg.default_value = Some("false".to_string()); + arg + }; + vec![ + DirectiveDef { + name: "include", + description: "whether this query should be included", + locations: &["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], + args: vec![if_arg.clone()], + }, + DirectiveDef { + name: "skip", + description: "whether this query should be skipped", + locations: &["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], + args: vec![if_arg], + }, + DirectiveDef { + name: "cached", + description: "whether this query should be cached (Hasura Cloud only)", + locations: &["QUERY"], + args: vec![ttl, refresh], + }, + ] +} + +fn write_directive( + registry: &Registry, + directive: &DirectiveDef, + sel: &IntroSelection, + out: &mut String, +) -> GResult<()> { + write_object(sel, out, |item, out| { + match item.field.as_str() { + "__typename" => write_json_string(out, "__Directive"), + "name" => write_json_string(out, directive.name), + "description" => write_json_string(out, directive.description), + "locations" => write_array(out, directive.locations.iter(), |loc, out| { + write_json_string(out, loc); + Ok(()) + })?, + "args" => { + let sub = subsel(item)?; + write_array(out, directive.args.iter(), |a, out| { + write_input_value(registry, a, sub, out) + })?; + } + // Hasura types isRepeatable as String! yet always returns null. + "isRepeatable" => out.push_str("null"), + other => { + return Err(internal(format!( + "unexpected field '{other}' on __Directive" + ))) + } + } + Ok(()) + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::serve::gql::schema_build::{self, Role}; + use crate::serve::model::{Column, Scalar, ServerModel, Table}; + use crate::serve::pg_catalog::RelationKind; + + fn test_registry() -> Registry { + let model = ServerModel { + tables: vec![Table { + name: "User".to_string(), + kind: RelationKind::Table, + description: None, + columns: vec![Column { + api_name: "id".to_string(), + db_name: "id".to_string(), + pg_type: "text".to_string(), + pg_type_schema: "pg_catalog".to_string(), + scalar: Scalar::String, + is_array: false, + nullable: false, + description: None, + }], + primary_key: vec!["id".to_string()], + object_relationships: vec![], + array_relationships: vec![], + admin_only: false, + public_aggregations: false, + }], + pg_schema: "public".to_string(), + response_limit: None, + }; + schema_build::build(&model, Role::Public) + } + + fn item(field: &str, selection: Option) -> IntroSelItem { + IntroSelItem { + alias: field.to_string(), + field: field.to_string(), + include_deprecated: false, + selection, + } + } + + fn sel(items: Vec) -> IntroSelection { + IntroSelection { items } + } + + fn type_query(name: &str, selection: IntroSelection) -> IntrospectionField { + IntrospectionField { + alias: "__type".to_string(), + field: "__type".to_string(), + type_name: Some(name.to_string()), + selection, + } + } + + #[test] + fn json_string_escaping() { + let mut out = String::new(); + write_json_string(&mut out, "a\"b\\c\nd\te\u{1}f🚀"); + assert_eq!(out, "\"a\\\"b\\\\c\\nd\\te\\u0001f🚀\""); + } + + #[test] + fn type_query_object_with_of_type_chain() { + let registry = test_registry(); + let field = type_query( + "User", + sel(vec![ + item("kind", None), + item("name", None), + item("description", None), + item( + "fields", + Some(sel(vec![ + item("name", None), + item( + "type", + Some(sel(vec![ + item("kind", None), + item("name", None), + item( + "ofType", + Some(sel(vec![item("kind", None), item("name", None)])), + ), + ])), + ), + ])), + ), + item("interfaces", Some(sel(vec![item("name", None)]))), + item("inputFields", Some(sel(vec![item("name", None)]))), + item("possibleTypes", Some(sel(vec![item("name", None)]))), + ]), + ); + assert_eq!( + resolve(®istry, &field).unwrap(), + r#"{"kind":"OBJECT","name":"User","description":"columns and relationships of \"User\"","fields":[{"name":"id","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String"}}}],"interfaces":[],"inputFields":null,"possibleTypes":null}"# + ); + } + + #[test] + fn type_query_missing_type_is_null() { + let registry = test_registry(); + let field = type_query("DoesNotExist", sel(vec![item("name", None)])); + assert_eq!(resolve(®istry, &field).unwrap(), "null"); + } + + #[test] + fn type_query_meta_enum_uses_alias() { + let registry = test_registry(); + let mut values = item("enumValues", Some(sel(vec![item("name", None)]))); + values.alias = "vals".to_string(); + let field = type_query("__TypeKind", sel(vec![item("__typename", None), values])); + assert_eq!( + resolve(®istry, &field).unwrap(), + r#"{"__typename":"__Type","vals":[{"name":"ENUM"},{"name":"INPUT_OBJECT"},{"name":"INTERFACE"},{"name":"LIST"},{"name":"NON_NULL"},{"name":"OBJECT"},{"name":"SCALAR"},{"name":"UNION"}]}"# + ); + } + + #[test] + fn schema_roots_and_directives() { + let registry = test_registry(); + let field = IntrospectionField { + alias: "__schema".to_string(), + field: "__schema".to_string(), + type_name: None, + selection: sel(vec![ + item("queryType", Some(sel(vec![item("name", None)]))), + item("mutationType", Some(sel(vec![item("name", None)]))), + item("subscriptionType", Some(sel(vec![item("name", None)]))), + item( + "directives", + Some(sel(vec![ + item("name", None), + item("locations", None), + item( + "args", + Some(sel(vec![ + item("name", None), + item("defaultValue", None), + item( + "type", + Some(sel(vec![ + item("kind", None), + item("ofType", Some(sel(vec![item("name", None)]))), + ])), + ), + ])), + ), + ])), + ), + ]), + }; + assert_eq!( + resolve(®istry, &field).unwrap(), + concat!( + r#"{"queryType":{"name":"query_root"},"mutationType":null,"subscriptionType":{"name":"subscription_root"},"#, + r#""directives":[{"name":"include","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","defaultValue":null,"type":{"kind":"NON_NULL","ofType":{"name":"Boolean"}}}]},"#, + r#"{"name":"skip","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","defaultValue":null,"type":{"kind":"NON_NULL","ofType":{"name":"Boolean"}}}]},"#, + r#"{"name":"cached","locations":["QUERY"],"args":[{"name":"ttl","defaultValue":"60","type":{"kind":"NON_NULL","ofType":{"name":"Int"}}},{"name":"refresh","defaultValue":"false","type":{"kind":"NON_NULL","ofType":{"name":"Boolean"}}}]}]}"# + ) + ); + } + + /// The nested TypeRef fragment of the standard introspection query: + /// `kind name` plus `depth` levels of `ofType`. + fn type_ref_sel(depth: usize) -> IntroSelection { + let mut items = vec![item("kind", None), item("name", None)]; + if depth > 0 { + items.push(item("ofType", Some(type_ref_sel(depth - 1)))); + } + sel(items) + } + + fn input_value_sel() -> IntroSelection { + sel(vec![ + item("name", None), + item("description", None), + item("type", Some(type_ref_sel(7))), + item("defaultValue", None), + ]) + } + + fn full_type_sel() -> IntroSelection { + sel(vec![ + item("kind", None), + item("name", None), + item("description", None), + item( + "fields", + Some(sel(vec![ + item("name", None), + item("description", None), + item("args", Some(input_value_sel())), + item("type", Some(type_ref_sel(7))), + item("isDeprecated", None), + item("deprecationReason", None), + ])), + ), + item("inputFields", Some(input_value_sel())), + item("interfaces", Some(type_ref_sel(7))), + item( + "enumValues", + Some(sel(vec![ + item("name", None), + item("description", None), + item("isDeprecated", None), + item("deprecationReason", None), + ])), + ), + item("possibleTypes", Some(type_ref_sel(7))), + ]) + } + + // Expected values come verbatim from the oracle snapshot + // introspection-full-public.json (compact-serialized). + #[test] + fn meta_types_match_oracle_full_type_fragment() { + let registry = test_registry(); + let render = |name: &str| resolve(®istry, &type_query(name, full_type_sel())).unwrap(); + assert_eq!( + (render("__Type"), render("__TypeKind")), + ( + r#"{"kind":"OBJECT","name":"__Type","description":null,"fields":[{"name":"description","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"enumValues","description":null,"args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"OBJECT","name":"__EnumValue","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fields","description":null,"args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"OBJECT","name":"__Field","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"inputFields","description":null,"args":[],"type":{"kind":"OBJECT","name":"__InputValue","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"interfaces","description":null,"args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"kind","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"__TypeKind","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"ofType","description":null,"args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"possibleTypes","description":null,"args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null}"#.to_string(), + r#"{"kind":"ENUM","name":"__TypeKind","description":null,"fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"ENUM","description":null,"isDeprecated":false,"deprecationReason":null},{"name":"INPUT_OBJECT","description":null,"isDeprecated":false,"deprecationReason":null},{"name":"INTERFACE","description":null,"isDeprecated":false,"deprecationReason":null},{"name":"LIST","description":null,"isDeprecated":false,"deprecationReason":null},{"name":"NON_NULL","description":null,"isDeprecated":false,"deprecationReason":null},{"name":"OBJECT","description":null,"isDeprecated":false,"deprecationReason":null},{"name":"SCALAR","description":null,"isDeprecated":false,"deprecationReason":null},{"name":"UNION","description":null,"isDeprecated":false,"deprecationReason":null}],"possibleTypes":null}"#.to_string() + ) + ); + } + + #[test] + fn schema_types_are_sorted_and_include_meta_types() { + let registry = test_registry(); + let field = IntrospectionField { + alias: "s".to_string(), + field: "__schema".to_string(), + type_name: None, + selection: sel(vec![item("types", Some(sel(vec![item("name", None)])))]), + }; + let out = resolve(®istry, &field).unwrap(); + let meta: Vec<&str> = [ + "__Directive", + "__EnumValue", + "__Field", + "__InputValue", + "__Schema", + "__Type", + "__TypeKind", + ] + .into_iter() + .filter(|n| out.contains(&format!("{{\"name\":\"{n}\"}}"))) + .collect(); + assert_eq!( + ( + meta.len(), + out.contains("\"User_stream_cursor_value_input\"},{\"name\":\"__Directive\"") + ), + (7, true) + ); + } +} diff --git a/packages/cli/src/serve/gql/mod.rs b/packages/cli/src/serve/gql/mod.rs new file mode 100644 index 0000000000..21294d734f --- /dev/null +++ b/packages/cli/src/serve/gql/mod.rs @@ -0,0 +1,3 @@ +pub mod introspection; +pub mod schema_build; +pub mod types; diff --git a/packages/cli/src/serve/gql/schema_build.rs b/packages/cli/src/serve/gql/schema_build.rs new file mode 100644 index 0000000000..74b9fac845 --- /dev/null +++ b/packages/cli/src/serve/gql/schema_build.rs @@ -0,0 +1,1343 @@ +//! Builds the per-role GraphQL type registry from the server model, +//! reproducing Hasura's generated schema shape exactly: naming, argument +//! order, descriptions, and role gating (aggregates, table visibility). + +use super::types::*; +use crate::serve::model::{Column, Scalar, ServerModel, Table}; +use crate::serve::pg_catalog::RelationKind; +use std::collections::BTreeMap; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum Role { + Admin, + Public, +} + +pub struct RoleSchema { + pub registry: Registry, + pub role: Role, +} + +fn scalar_type_name(c: &Column) -> String { + c.scalar.gql_name(&c.pg_type) +} + +/// Column output type, e.g. `String!`, `[String!]!`, `numeric`. +fn column_type_ref(c: &Column) -> TypeRef { + let base = TypeRef::named(&scalar_type_name(c)); + let inner = if c.is_array { + TypeRef::list(TypeRef::non_null(base)) + } else { + base + }; + if c.nullable { + inner + } else { + TypeRef::non_null(inner) + } +} + +fn visible_tables(model: &ServerModel, role: Role) -> Vec<&Table> { + model + .tables + .iter() + .filter(|t| role == Role::Admin || !t.admin_only) + .collect() +} + +fn aggregations_enabled(table: &Table, role: Role) -> bool { + role == Role::Admin || table.public_aggregations +} + +/// Whether the table gets a `_by_pk` root field. +fn has_by_pk(table: &Table) -> bool { + !table.primary_key.is_empty() && table.kind == RelationKind::Table +} + +fn select_args(table_name: &str) -> Vec { + vec![ + InputValueDef::new( + "distinct_on", + Some("distinct select on columns"), + TypeRef::list(TypeRef::non_null(TypeRef::named(&format!( + "{table_name}_select_column" + )))), + ), + InputValueDef::new( + "limit", + Some("limit the number of rows returned"), + TypeRef::named("Int"), + ), + InputValueDef::new( + "offset", + Some("skip the first n rows. Use only with order_by"), + TypeRef::named("Int"), + ), + InputValueDef::new( + "order_by", + Some("sort the rows by one or more columns"), + TypeRef::list(TypeRef::non_null(TypeRef::named(&format!( + "{table_name}_order_by" + )))), + ), + InputValueDef::new( + "where", + Some("filter the rows returned"), + TypeRef::named(&format!("{table_name}_bool_exp")), + ), + ] +} + +/// The numeric aggregate operations in Hasura's field order within +/// `_aggregate_fields` (alphabetical among all ops). +fn numeric_ops() -> Vec<&'static str> { + vec![ + "avg", + "stddev", + "stddev_pop", + "stddev_samp", + "sum", + "var_pop", + "var_samp", + "variance", + ] +} + +/// Result scalar of an aggregate op over a column. +fn agg_op_result_type(op: &str, c: &Column) -> TypeRef { + match op { + // sum keeps the column's scalar; everything else yields Float. + "sum" => TypeRef::named(&scalar_type_name(c)), + "min" | "max" => column_min_max_type(c), + _ => TypeRef::named("Float"), + } +} + +fn column_min_max_type(c: &Column) -> TypeRef { + TypeRef::named(&scalar_type_name(c)) +} + +/// Columns eligible for min/max fields (Hasura: all comparable scalars, +/// excluding json/jsonb; arrays are excluded as well). `Scalar::Other` +/// covers pg types like bytea with no min/max in Postgres — including them +/// would generate fields whose execution PG rejects. +fn min_max_columns(table: &Table) -> Vec<&Column> { + table + .columns + .iter() + .filter(|c| { + !c.is_array + && !matches!( + c.scalar, + Scalar::Jsonb | Scalar::Json | Scalar::Boolean | Scalar::Other + ) + }) + .collect() +} + +fn numeric_columns(table: &Table) -> Vec<&Column> { + table + .columns + .iter() + .filter(|c| !c.is_array && c.scalar.is_numeric()) + .collect() +} + +/// Tables that are the remote side of some array relationship visible to +/// this role — they need `_aggregate_order_by` (+ per-op order_by input +/// types), regardless of allow_aggregations. +fn aggregate_order_by_targets(model: &ServerModel, role: Role) -> Vec { + let mut names: Vec = vec![]; + for t in visible_tables(model, role) { + for rel in &t.array_relationships { + if !names.contains(&rel.remote_table) { + names.push(rel.remote_table.clone()); + } + } + } + names +} + +/// Whether any visible table's bool_exp needs `_aggregate` predicates +/// for this remote table (admin only — gated by allow_aggregations of the +/// remote table). +fn aggregate_bool_exp_targets(model: &ServerModel, role: Role) -> Vec { + let mut names: Vec = vec![]; + for t in visible_tables(model, role) { + for rel in &t.array_relationships { + let remote_aggregatable = model + .table(&rel.remote_table) + .map(|rt| aggregations_enabled(rt, role)) + .unwrap_or(false); + if remote_aggregatable && !names.contains(&rel.remote_table) { + names.push(rel.remote_table.clone()); + } + } + } + names +} + +pub fn build(model: &ServerModel, role: Role) -> Registry { + build_internal(model, role).0 +} + +/// Startup validation: fails when a user entity name collides with a +/// generated/built-in type name (like Hasura fails table tracking on +/// conflicts). The admin registry is a superset of every role's types, so +/// checking it covers all roles. +pub fn check_type_collisions(model: &ServerModel) -> anyhow::Result<()> { + let (_, mut collisions) = build_internal(model, Role::Admin); + if collisions.is_empty() { + return Ok(()); + } + collisions.sort(); + collisions.dedup(); + Err(anyhow::anyhow!( + "GraphQL type name collision(s): {}. An entity in schema.graphql clashes with a built-in or generated type name (e.g. \"_aggregate\", \"_bool_exp\", scalar or root type names). Rename the conflicting entity.", + collisions.join(", ") + )) +} + +fn build_internal(model: &ServerModel, role: Role) -> (Registry, Vec) { + let mut b = Builder { + model, + role, + types: BTreeMap::new(), + collisions: Vec::new(), + }; + b.build_base_scalars_and_enums(); + + let tables = visible_tables(model, role); + for table in &tables { + b.build_table_types(table); + } + for name in aggregate_order_by_targets(model, role) { + if let Some(t) = model.table(&name) { + b.build_aggregate_order_by_types(t); + } + } + for name in aggregate_bool_exp_targets(model, role) { + if let Some(t) = model.table(&name) { + b.build_aggregate_bool_exp_types(t); + } + } + b.build_roots(&tables); + b.build_meta_types(); + + ( + Registry { + types: b.types, + query_root: "query_root".to_string(), + mutation_root: None, + subscription_root: "subscription_root".to_string(), + }, + b.collisions, + ) +} + +/// A synthetic column used to force on-demand creation of a shared +/// `_comparison_exp` type that is referenced unconditionally. +fn stub_column(pg_type: &str, scalar: Scalar) -> Column { + Column { + api_name: "_".into(), + db_name: "_".into(), + pg_type: pg_type.into(), + pg_type_schema: "pg_catalog".into(), + scalar, + is_array: false, + nullable: true, + description: None, + } +} + +struct Builder<'a> { + model: &'a ServerModel, + role: Role, + types: BTreeMap, + /// Names that were defined twice (or squatted by a user entity) — + /// nothing in the builder legitimately re-adds a name, so any duplicate + /// is a genuine collision surfaced by check_type_collisions. + collisions: Vec, +} + +impl<'a> Builder<'a> { + fn add(&mut self, def: TypeDef) { + let name = def.name().to_string(); + if self.types.insert(name.clone(), def).is_some() { + self.collisions.push(name); + } + } + + fn add_scalar(&mut self, name: &str) { + match self.types.get(name) { + None => self.add(TypeDef::Scalar { + name: name.to_string(), + description: None, + }), + Some(TypeDef::Scalar { .. }) => {} + Some(_) => self.collisions.push(name.to_string()), + } + } + + fn build_base_scalars_and_enums(&mut self) { + for s in ["Boolean", "Float", "Int", "String"] { + self.add_scalar(s); + } + self.add(TypeDef::Enum { + name: "order_by".to_string(), + description: Some("column ordering options".to_string()), + values: vec![ + EnumValueDef { + name: "asc".into(), + description: Some("in ascending order, nulls last".into()), + }, + EnumValueDef { + name: "asc_nulls_first".into(), + description: Some("in ascending order, nulls first".into()), + }, + EnumValueDef { + name: "asc_nulls_last".into(), + description: Some("in ascending order, nulls last".into()), + }, + EnumValueDef { + name: "desc".into(), + description: Some("in descending order, nulls first".into()), + }, + EnumValueDef { + name: "desc_nulls_first".into(), + description: Some("in descending order, nulls first".into()), + }, + EnumValueDef { + name: "desc_nulls_last".into(), + description: Some("in descending order, nulls last".into()), + }, + ], + }); + self.add(TypeDef::Enum { + name: "cursor_ordering".to_string(), + description: Some("ordering argument of a cursor".to_string()), + values: vec![ + EnumValueDef { + name: "ASC".into(), + description: Some("ascending ordering of the cursor".into()), + }, + EnumValueDef { + name: "DESC".into(), + description: Some("descending ordering of the cursor".into()), + }, + ], + }); + } + + /// `_comparison_exp`, shared across tables; created on demand. + fn comparison_exp_name(&mut self, c: &Column) -> String { + let scalar = scalar_type_name(c); + self.add_scalar(&scalar); + let name = if c.is_array { + format!("{scalar}_array_comparison_exp") + } else { + format!("{scalar}_comparison_exp") + }; + if let Some(existing) = self.types.get(&name) { + if !matches!(existing, TypeDef::InputObject { .. }) { + self.collisions.push(name.clone()); + } + return name; + } + + let value_ty = if c.is_array { + TypeRef::list(TypeRef::non_null(TypeRef::named(&scalar))) + } else { + TypeRef::named(&scalar) + }; + let list_ty = TypeRef::list(TypeRef::non_null(value_ty.clone())); + + let mut fields: Vec = Vec::new(); + let mut push = |n: &str, d: Option<&str>, ty: TypeRef| { + fields.push(InputValueDef::new(n, d, ty)); + }; + + if c.is_array { + push( + "_contained_in", + Some("is the array contained in the given array value"), + value_ty.clone(), + ); + push( + "_contains", + Some("does the array contain the given value"), + value_ty.clone(), + ); + } + if c.scalar == Scalar::Jsonb && !c.is_array { + push("_cast", None, TypeRef::named("jsonb_cast_exp")); + self.build_jsonb_cast_exp(); + push( + "_contained_in", + Some("is the column contained in the given json value"), + value_ty.clone(), + ); + push( + "_contains", + Some("does the column contain the given json value at the top level"), + value_ty.clone(), + ); + } + push("_eq", None, value_ty.clone()); + push("_gt", None, value_ty.clone()); + push("_gte", None, value_ty.clone()); + if c.scalar == Scalar::Jsonb && !c.is_array { + push( + "_has_key", + Some("does the string exist as a top-level key in the column"), + TypeRef::named("String"), + ); + push( + "_has_keys_all", + Some("do all of these strings exist as top-level keys in the column"), + TypeRef::list(TypeRef::non_null(TypeRef::named("String"))), + ); + push( + "_has_keys_any", + Some("do any of these strings exist as top-level keys in the column"), + TypeRef::list(TypeRef::non_null(TypeRef::named("String"))), + ); + } + if c.scalar == Scalar::String && !c.is_array { + push( + "_ilike", + Some("does the column match the given case-insensitive pattern"), + TypeRef::named(&scalar), + ); + } + push("_in", None, list_ty.clone()); + if c.scalar == Scalar::String && !c.is_array { + push( + "_iregex", + Some("does the column match the given POSIX regular expression, case insensitive"), + TypeRef::named(&scalar), + ); + } + push("_is_null", None, TypeRef::named("Boolean")); + if c.scalar == Scalar::String && !c.is_array { + push( + "_like", + Some("does the column match the given pattern"), + TypeRef::named(&scalar), + ); + } + push("_lt", None, value_ty.clone()); + push("_lte", None, value_ty.clone()); + push("_neq", None, value_ty.clone()); + if c.scalar == Scalar::String && !c.is_array { + push( + "_nilike", + Some("does the column NOT match the given case-insensitive pattern"), + TypeRef::named(&scalar), + ); + } + push("_nin", None, list_ty); + if c.scalar == Scalar::String && !c.is_array { + push( + "_niregex", + Some( + "does the column NOT match the given POSIX regular expression, case insensitive", + ), + TypeRef::named(&scalar), + ); + push( + "_nlike", + Some("does the column NOT match the given pattern"), + TypeRef::named(&scalar), + ); + push( + "_nregex", + Some( + "does the column NOT match the given POSIX regular expression, case sensitive", + ), + TypeRef::named(&scalar), + ); + push( + "_nsimilar", + Some("does the column NOT match the given SQL regular expression"), + TypeRef::named(&scalar), + ); + push( + "_regex", + Some("does the column match the given POSIX regular expression, case sensitive"), + TypeRef::named(&scalar), + ); + push( + "_similar", + Some("does the column match the given SQL regular expression"), + TypeRef::named(&scalar), + ); + } + + // Hasura sorts comparison-exp fields alphabetically. + fields.sort_by(|a, b| a.name.cmp(&b.name)); + + self.add(TypeDef::InputObject { + name: name.clone(), + description: Some(format!( + "Boolean expression to compare columns of type \"{scalar}\". All fields are combined with logical 'AND'." + )), + fields, + }); + name + } + + fn build_jsonb_cast_exp(&mut self) { + if let Some(existing) = self.types.get("jsonb_cast_exp") { + if !matches!(existing, TypeDef::InputObject { .. }) { + self.collisions.push("jsonb_cast_exp".to_string()); + } + return; + } + // The String member references String_comparison_exp; make sure it + // exists. + let cmp = self.comparison_exp_name(&stub_column("text", Scalar::String)); + self.add(TypeDef::InputObject { + name: "jsonb_cast_exp".to_string(), + description: None, + fields: vec![InputValueDef::new("String", None, TypeRef::named(&cmp))], + }); + } + + fn build_table_types(&mut self, table: &Table) { + let t = &table.name; + let role = self.role; + + // Object type + let mut fields: Vec = Vec::new(); + for c in &table.columns { + let mut args = vec![]; + if matches!(c.scalar, Scalar::Jsonb | Scalar::Json) && !c.is_array { + args.push(InputValueDef::new( + "path", + Some("JSON select path"), + TypeRef::named("String"), + )); + } + fields.push(FieldDef { + name: c.api_name.clone(), + description: c.description.clone(), + args, + ty: column_type_ref(c), + kind: FieldKind::Column { + column: c.api_name.clone(), + }, + }); + } + for rel in &table.object_relationships { + let Some(remote) = self.model.table(&rel.remote_table) else { + continue; + }; + // Hasura's manual object relationships are always nullable, even + // when the fk column is NOT NULL, because they don't prove + // existence (pinned by snapshot: Gravatar.owner: User). + fields.push(FieldDef { + name: rel.name.clone(), + description: Some("An object relationship".to_string()), + args: vec![], + ty: TypeRef::named(&remote.name), + kind: FieldKind::ObjectRel { + rel: rel.name.clone(), + }, + }); + } + for rel in &table.array_relationships { + let Some(remote) = self.model.table(&rel.remote_table) else { + continue; + }; + fields.push(FieldDef { + name: rel.name.clone(), + description: Some("An array relationship".to_string()), + args: select_args(&remote.name), + ty: TypeRef::non_null_list_of_non_null(&remote.name), + kind: FieldKind::ArrayRel { + rel: rel.name.clone(), + }, + }); + if aggregations_enabled(remote, role) { + fields.push(FieldDef { + name: format!("{}_aggregate", rel.name), + description: Some("An aggregate relationship".to_string()), + args: select_args(&remote.name), + ty: TypeRef::non_null(TypeRef::named(&format!("{}_aggregate", remote.name))), + kind: FieldKind::ArrayRelAggregate { + rel: rel.name.clone(), + }, + }); + } + } + fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::Object { + name: t.clone(), + description: Some( + table + .description + .clone() + .unwrap_or_else(|| format!("columns and relationships of \"{t}\"")), + ), + fields, + }); + + // bool_exp + let mut bool_fields: Vec = vec![ + InputValueDef::new( + "_and", + None, + TypeRef::list(TypeRef::non_null(TypeRef::named(&format!("{t}_bool_exp")))), + ), + InputValueDef::new("_not", None, TypeRef::named(&format!("{t}_bool_exp"))), + InputValueDef::new( + "_or", + None, + TypeRef::list(TypeRef::non_null(TypeRef::named(&format!("{t}_bool_exp")))), + ), + ]; + for c in &table.columns { + let cmp = self.comparison_exp_name(c); + bool_fields.push(InputValueDef::new(&c.api_name, None, TypeRef::named(&cmp))); + } + for rel in &table.object_relationships { + bool_fields.push(InputValueDef::new( + &rel.name, + None, + TypeRef::named(&format!("{}_bool_exp", rel.remote_table)), + )); + } + for rel in &table.array_relationships { + bool_fields.push(InputValueDef::new( + &rel.name, + None, + TypeRef::named(&format!("{}_bool_exp", rel.remote_table)), + )); + let remote_aggregatable = self + .model + .table(&rel.remote_table) + .map(|rt| aggregations_enabled(rt, role)) + .unwrap_or(false); + if remote_aggregatable { + bool_fields.push(InputValueDef::new( + &format!("{}_aggregate", rel.name), + None, + TypeRef::named(&format!("{}_aggregate_bool_exp", rel.remote_table)), + )); + } + } + bool_fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::InputObject { + name: format!("{t}_bool_exp"), + description: Some(format!( + "Boolean expression to filter rows from the table \"{t}\". All fields are combined with a logical 'AND'." + )), + fields: bool_fields, + }); + + // order_by + let mut order_fields: Vec = table + .columns + .iter() + .map(|c| InputValueDef::new(&c.api_name, None, TypeRef::named("order_by"))) + .collect(); + for rel in &table.object_relationships { + order_fields.push(InputValueDef::new( + &rel.name, + None, + TypeRef::named(&format!("{}_order_by", rel.remote_table)), + )); + } + for rel in &table.array_relationships { + order_fields.push(InputValueDef::new( + &format!("{}_aggregate", rel.name), + None, + TypeRef::named(&format!("{}_aggregate_order_by", rel.remote_table)), + )); + } + order_fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::InputObject { + name: format!("{t}_order_by"), + description: Some(format!( + "Ordering options when selecting data from \"{t}\"." + )), + fields: order_fields, + }); + + // select_column enum + let mut col_values: Vec = table + .columns + .iter() + .map(|c| EnumValueDef { + name: c.api_name.clone(), + description: Some("column name".to_string()), + }) + .collect(); + col_values.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::Enum { + name: format!("{t}_select_column"), + description: Some(format!("select columns of table \"{t}\"")), + values: col_values, + }); + + // stream cursor inputs + self.add(TypeDef::InputObject { + name: format!("{t}_stream_cursor_input"), + description: Some(format!("Streaming cursor of the table \"{t}\"")), + fields: vec![ + InputValueDef::new( + "initial_value", + Some("Stream column input with initial value"), + TypeRef::non_null(TypeRef::named(&format!("{t}_stream_cursor_value_input"))), + ), + InputValueDef::new( + "ordering", + Some("cursor ordering"), + TypeRef::named("cursor_ordering"), + ), + ], + }); + let mut cursor_fields: Vec = table + .columns + .iter() + .map(|c| { + let base = TypeRef::named(&scalar_type_name(c)); + let ty = if c.is_array { + TypeRef::list(TypeRef::non_null(base)) + } else { + base + }; + InputValueDef::new(&c.api_name, c.description.as_deref(), ty) + }) + .collect(); + cursor_fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::InputObject { + name: format!("{t}_stream_cursor_value_input"), + description: Some( + "Initial value of the column from where the streaming should start".to_string(), + ), + fields: cursor_fields, + }); + + // aggregate types (only when this role can aggregate this table) + if aggregations_enabled(table, role) { + self.build_aggregate_types(table); + } + } + + fn build_aggregate_types(&mut self, table: &Table) { + let t = &table.name; + self.add(TypeDef::Object { + name: format!("{t}_aggregate"), + description: Some(format!("aggregated selection of \"{t}\"")), + fields: vec![ + FieldDef { + name: "aggregate".to_string(), + description: None, + args: vec![], + ty: TypeRef::named(&format!("{t}_aggregate_fields")), + kind: FieldKind::AggregateBody, + }, + FieldDef { + name: "nodes".to_string(), + description: None, + args: vec![], + ty: TypeRef::non_null_list_of_non_null(t), + kind: FieldKind::AggregateNodes, + }, + ], + }); + + let numeric_cols = numeric_columns(table); + let mut agg_fields: Vec = vec![FieldDef { + name: "count".to_string(), + description: None, + args: vec![ + InputValueDef::new( + "columns", + None, + TypeRef::list(TypeRef::non_null(TypeRef::named(&format!( + "{t}_select_column" + )))), + ), + InputValueDef::new("distinct", None, TypeRef::named("Boolean")), + ], + ty: TypeRef::non_null(TypeRef::named("Int")), + kind: FieldKind::AggregateCount, + }]; + for op in ["max", "min"] { + let cols = min_max_columns(table); + if cols.is_empty() { + continue; + } + agg_fields.push(FieldDef { + name: op.to_string(), + description: None, + args: vec![], + ty: TypeRef::named(&format!("{t}_{op}_fields")), + kind: FieldKind::AggregateOp { op: op.to_string() }, + }); + let mut op_fields: Vec = cols + .iter() + .map(|c| FieldDef { + name: c.api_name.clone(), + description: c.description.clone(), + args: vec![], + ty: agg_op_result_type(op, c), + kind: FieldKind::AggregateOpColumn { + op: op.to_string(), + column: c.api_name.clone(), + }, + }) + .collect(); + op_fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::Object { + name: format!("{t}_{op}_fields"), + description: Some(format!("aggregate {op} on columns")), + fields: op_fields, + }); + } + if !numeric_cols.is_empty() { + for op in numeric_ops() { + agg_fields.push(FieldDef { + name: op.to_string(), + description: None, + args: vec![], + ty: TypeRef::named(&format!("{t}_{op}_fields")), + kind: FieldKind::AggregateOp { op: op.to_string() }, + }); + let mut op_fields: Vec = numeric_cols + .iter() + .map(|c| FieldDef { + name: c.api_name.clone(), + description: c.description.clone(), + args: vec![], + ty: agg_op_result_type(op, c), + kind: FieldKind::AggregateOpColumn { + op: op.to_string(), + column: c.api_name.clone(), + }, + }) + .collect(); + op_fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::Object { + name: format!("{t}_{op}_fields"), + description: Some(format!("aggregate {op} on columns")), + fields: op_fields, + }); + } + } + agg_fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::Object { + name: format!("{t}_aggregate_fields"), + description: Some(format!("aggregate fields of \"{t}\"")), + fields: agg_fields, + }); + } + + /// `_aggregate_order_by` + per-op order_by inputs, for tables that + /// are the remote side of array relationships. + fn build_aggregate_order_by_types(&mut self, table: &Table) { + let t = &table.name; + if let Some(existing) = self.types.get(&format!("{t}_aggregate_order_by")) { + if !matches!(existing, TypeDef::InputObject { .. }) { + self.collisions.push(format!("{t}_aggregate_order_by")); + } + return; + } + let numeric_cols = numeric_columns(table); + let mm_cols = min_max_columns(table); + + let mut fields: Vec = vec![InputValueDef::new( + "count", + None, + TypeRef::named("order_by"), + )]; + + for op in ["max", "min"] { + if mm_cols.is_empty() { + continue; + } + fields.push(InputValueDef::new( + op, + None, + TypeRef::named(&format!("{t}_{op}_order_by")), + )); + let mut op_fields: Vec = mm_cols + .iter() + .map(|c| InputValueDef::new(&c.api_name, None, TypeRef::named("order_by"))) + .collect(); + op_fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::InputObject { + name: format!("{t}_{op}_order_by"), + description: Some(format!("order by {op}() on columns of table \"{t}\"")), + fields: op_fields, + }); + } + if !numeric_cols.is_empty() { + for op in numeric_ops() { + fields.push(InputValueDef::new( + op, + None, + TypeRef::named(&format!("{t}_{op}_order_by")), + )); + let mut op_fields: Vec = numeric_cols + .iter() + .map(|c| InputValueDef::new(&c.api_name, None, TypeRef::named("order_by"))) + .collect(); + op_fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::InputObject { + name: format!("{t}_{op}_order_by"), + description: Some(format!("order by {op}() on columns of table \"{t}\"")), + fields: op_fields, + }); + } + } + fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::InputObject { + name: format!("{t}_aggregate_order_by"), + description: Some(format!("order by aggregate values of table \"{t}\"")), + fields, + }); + } + + /// `_aggregate_bool_exp` types for aggregate predicates in bool_exps + /// (admin, or aggregatable tables). + fn build_aggregate_bool_exp_types(&mut self, table: &Table) { + let t = &table.name; + if let Some(existing) = self.types.get(&format!("{t}_aggregate_bool_exp")) { + if !matches!(existing, TypeDef::InputObject { .. }) { + self.collisions.push(format!("{t}_aggregate_bool_exp")); + } + return; + } + let bool_cols: Vec<&Column> = table + .columns + .iter() + .filter(|c| !c.is_array && c.scalar == Scalar::Boolean) + .collect(); + + let mut fields: Vec = Vec::new(); + for (op, cols) in [("bool_and", &bool_cols), ("bool_or", &bool_cols)] { + if cols.is_empty() { + continue; + } + // The `predicate` field below references Boolean_comparison_exp + // unconditionally; guarantee it exists even if no visible table + // column created it on demand. + self.comparison_exp_name(&stub_column("bool", Scalar::Boolean)); + fields.push(InputValueDef::new( + op, + None, + TypeRef::named(&format!("{t}_aggregate_bool_exp_{op}")), + )); + let sel_name = + format!("{t}_select_column_{t}_aggregate_bool_exp_{op}_arguments_columns"); + let mut sel_values: Vec = cols + .iter() + .map(|c| EnumValueDef { + name: c.api_name.clone(), + description: Some("column name".to_string()), + }) + .collect(); + sel_values.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::Enum { + name: sel_name.clone(), + description: Some(format!( + "select \"{t}_aggregate_bool_exp_{op}_arguments_columns\" columns of table \"{t}\"" + )), + values: sel_values, + }); + self.add(TypeDef::InputObject { + name: format!("{t}_aggregate_bool_exp_{op}"), + description: None, + fields: vec![ + InputValueDef::new( + "arguments", + None, + TypeRef::non_null(TypeRef::named(&sel_name)), + ), + InputValueDef::new("distinct", None, TypeRef::named("Boolean")), + InputValueDef::new("filter", None, TypeRef::named(&format!("{t}_bool_exp"))), + InputValueDef::new( + "predicate", + None, + TypeRef::non_null(TypeRef::named("Boolean_comparison_exp")), + ), + ], + }); + } + // The count `predicate` references Int_comparison_exp + // unconditionally; without this, a schema with no int4 column would + // reference a type that was never registered. + self.comparison_exp_name(&stub_column("int4", Scalar::Int)); + fields.push(InputValueDef::new( + "count", + None, + TypeRef::named(&format!("{t}_aggregate_bool_exp_count")), + )); + self.add(TypeDef::InputObject { + name: format!("{t}_aggregate_bool_exp_count"), + description: None, + fields: vec![ + InputValueDef::new( + "arguments", + None, + TypeRef::list(TypeRef::non_null(TypeRef::named(&format!( + "{t}_select_column" + )))), + ), + InputValueDef::new("distinct", None, TypeRef::named("Boolean")), + InputValueDef::new("filter", None, TypeRef::named(&format!("{t}_bool_exp"))), + InputValueDef::new( + "predicate", + None, + TypeRef::non_null(TypeRef::named("Int_comparison_exp")), + ), + ], + }); + fields.sort_by(|a, b| a.name.cmp(&b.name)); + self.add(TypeDef::InputObject { + name: format!("{t}_aggregate_bool_exp"), + description: None, + fields, + }); + } + + /// The `__Schema`/`__Type`/... meta types as Hasura reports them in its + /// own `types` list. Hasura's shapes are degenerate — list fields carry + /// their bare element type, and most nullable/scalar fields (even + /// `isRepeatable` and `isDeprecated`) come out as `String!`; reproduced + /// verbatim from the introspection-full-*.json oracle. There is no + /// `__DirectiveLocation` type: `locations` is `String!` too. + fn build_meta_types(&mut self) { + fn meta_field(name: &str, ty: TypeRef) -> FieldDef { + FieldDef { + name: name.to_string(), + description: None, + args: vec![], + ty, + kind: FieldKind::Introspection, + } + } + fn string_nn() -> TypeRef { + TypeRef::non_null(TypeRef::named("String")) + } + + self.add(TypeDef::Object { + name: "__Directive".to_string(), + description: None, + fields: vec![ + meta_field("args", TypeRef::named("__InputValue")), + meta_field("description", string_nn()), + meta_field("isRepeatable", string_nn()), + meta_field("locations", string_nn()), + meta_field("name", string_nn()), + ], + }); + self.add(TypeDef::Object { + name: "__EnumValue".to_string(), + description: None, + fields: vec![ + meta_field("deprecationReason", string_nn()), + meta_field("description", string_nn()), + meta_field("isDeprecated", string_nn()), + meta_field("name", string_nn()), + ], + }); + self.add(TypeDef::Object { + name: "__Field".to_string(), + description: None, + fields: vec![ + meta_field("args", TypeRef::named("__InputValue")), + meta_field("deprecationReason", string_nn()), + meta_field("description", string_nn()), + meta_field("isDeprecated", string_nn()), + meta_field("name", string_nn()), + meta_field("type", TypeRef::named("__Type")), + ], + }); + self.add(TypeDef::Object { + name: "__InputValue".to_string(), + description: None, + fields: vec![ + meta_field("defaultValue", string_nn()), + meta_field("description", string_nn()), + meta_field("name", string_nn()), + meta_field("type", TypeRef::named("__Type")), + ], + }); + self.add(TypeDef::Object { + name: "__Schema".to_string(), + description: None, + fields: vec![ + meta_field("description", string_nn()), + meta_field("directives", TypeRef::named("__Directive")), + meta_field("mutationType", TypeRef::named("__Type")), + meta_field("queryType", TypeRef::named("__Type")), + meta_field("subscriptionType", TypeRef::named("__Type")), + meta_field("types", TypeRef::named("__Type")), + ], + }); + let include_deprecated = { + let mut arg = InputValueDef::new("includeDeprecated", None, TypeRef::named("Boolean")); + arg.default_value = Some("false".to_string()); + arg + }; + self.add(TypeDef::Object { + name: "__Type".to_string(), + description: None, + fields: vec![ + meta_field("description", string_nn()), + FieldDef { + name: "enumValues".to_string(), + description: None, + args: vec![include_deprecated.clone()], + ty: TypeRef::named("__EnumValue"), + kind: FieldKind::Introspection, + }, + FieldDef { + name: "fields".to_string(), + description: None, + args: vec![include_deprecated], + ty: TypeRef::named("__Field"), + kind: FieldKind::Introspection, + }, + meta_field("inputFields", TypeRef::named("__InputValue")), + meta_field("interfaces", TypeRef::named("__Type")), + meta_field("kind", TypeRef::non_null(TypeRef::named("__TypeKind"))), + meta_field("name", string_nn()), + meta_field("ofType", TypeRef::named("__Type")), + meta_field("possibleTypes", TypeRef::named("__Type")), + ], + }); + self.add(TypeDef::Enum { + name: "__TypeKind".to_string(), + description: None, + values: [ + "ENUM", + "INPUT_OBJECT", + "INTERFACE", + "LIST", + "NON_NULL", + "OBJECT", + "SCALAR", + "UNION", + ] + .iter() + .map(|n| EnumValueDef { + name: n.to_string(), + description: None, + }) + .collect(), + }); + } + + fn build_roots(&mut self, tables: &[&Table]) { + let mut query_fields: Vec = Vec::new(); + let mut sub_fields: Vec = Vec::new(); + + for table in tables { + let t = &table.name; + let select = FieldDef { + name: t.clone(), + description: Some(format!("fetch data from the table: \"{t}\"")), + args: select_args(t), + ty: TypeRef::non_null_list_of_non_null(t), + kind: FieldKind::SelectMany { table: t.clone() }, + }; + query_fields.push(select.clone()); + sub_fields.push(select); + + if aggregations_enabled(table, self.role) { + let agg = FieldDef { + name: format!("{t}_aggregate"), + description: Some(format!("fetch aggregated fields from the table: \"{t}\"")), + args: select_args(t), + ty: TypeRef::non_null(TypeRef::named(&format!("{t}_aggregate"))), + kind: FieldKind::SelectAggregate { table: t.clone() }, + }; + query_fields.push(agg.clone()); + sub_fields.push(agg); + } + + if has_by_pk(table) { + let args: Vec = table + .primary_key + .iter() + .filter_map(|pk_db| { + let c = table.columns.iter().find(|c| &c.db_name == pk_db)?; + Some(InputValueDef::new( + &c.api_name, + None, + TypeRef::non_null(TypeRef::named(&scalar_type_name(c))), + )) + }) + .collect(); + let by_pk = FieldDef { + name: format!("{t}_by_pk"), + description: Some(format!( + "fetch data from the table: \"{t}\" using primary key columns" + )), + args, + ty: TypeRef::named(t), + kind: FieldKind::SelectByPk { table: t.clone() }, + }; + query_fields.push(by_pk.clone()); + sub_fields.push(by_pk); + } + + sub_fields.push(FieldDef { + name: format!("{t}_stream"), + description: Some(format!( + "fetch data from the table in a streaming manner: \"{t}\"" + )), + args: vec![ + InputValueDef::new( + "batch_size", + Some("maximum number of rows returned in a single batch"), + TypeRef::non_null(TypeRef::named("Int")), + ), + InputValueDef::new( + "cursor", + Some("cursor to stream the results returned by the query"), + TypeRef::non_null(TypeRef::list(TypeRef::named(&format!( + "{t}_stream_cursor_input" + )))), + ), + InputValueDef::new( + "where", + Some("filter the rows returned"), + TypeRef::named(&format!("{t}_bool_exp")), + ), + ], + ty: TypeRef::non_null_list_of_non_null(t), + kind: FieldKind::SelectStream { table: t.clone() }, + }); + } + + query_fields.sort_by(|a, b| a.name.cmp(&b.name)); + sub_fields.sort_by(|a, b| a.name.cmp(&b.name)); + + self.add(TypeDef::Object { + name: "query_root".to_string(), + description: None, + fields: query_fields, + }); + self.add(TypeDef::Object { + name: "subscription_root".to_string(), + description: None, + fields: sub_fields, + }); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::serve::model::{ArrayRelationship, Column, Scalar, ServerModel, Table}; + + fn col(api: &str, pg_type: &str, scalar: Scalar) -> Column { + Column { + api_name: api.to_string(), + db_name: api.to_string(), + pg_type: pg_type.to_string(), + pg_type_schema: "pg_catalog".to_string(), + scalar, + is_array: false, + nullable: false, + description: None, + } + } + + fn table(name: &str, columns: Vec) -> Table { + Table { + name: name.to_string(), + kind: crate::serve::pg_catalog::RelationKind::Table, + description: None, + columns, + primary_key: vec!["id".to_string()], + object_relationships: vec![], + array_relationships: vec![], + admin_only: false, + public_aggregations: false, + } + } + + fn model(tables: Vec) -> ServerModel { + let mut tables = tables; + tables.sort_by(|a, b| a.name.cmp(&b.name)); + ServerModel { + tables, + pg_schema: "public".to_string(), + response_limit: None, + } + } + + /// No table has an int4 or bool column, yet the count/bool predicates of + /// `_aggregate_bool_exp_*` reference Int/Boolean_comparison_exp. + #[test] + fn aggregate_bool_exp_predicate_types_always_registered() { + let mut owner = table("Owner", vec![col("id", "text", Scalar::String)]); + owner.array_relationships.push(ArrayRelationship { + name: "pets".to_string(), + remote_table: "Pet".to_string(), + remote_db_column: "owner_id".to_string(), + }); + let mut pet = table( + "Pet", + vec![ + col("id", "text", Scalar::String), + col("owner_id", "text", Scalar::String), + col("vaccinated", "bool", Scalar::Boolean), + ], + ); + pet.public_aggregations = true; + let registry = build(&model(vec![owner, pet]), Role::Public); + assert_eq!( + ( + registry.get("Pet_aggregate_bool_exp_count").is_some(), + registry.get("Int_comparison_exp").is_some(), + registry.get("Boolean_comparison_exp").is_some(), + ), + (true, true, true) + ); + } + + /// bytea-like columns (Scalar::Other) have no min/max in Postgres; they + /// must not appear in `_min_fields`/`_max_fields`. + #[test] + fn other_scalar_columns_excluded_from_min_max() { + let mut t = table( + "Blob", + vec![ + col("id", "text", Scalar::String), + col("payload", "bytea", Scalar::Other), + ], + ); + t.public_aggregations = true; + let registry = build(&model(vec![t]), Role::Public); + let min_fields = match registry.get("Blob_min_fields") { + Some(TypeDef::Object { fields, .. }) => { + fields.iter().map(|f| f.name.clone()).collect::>() + } + _ => panic!("Blob_min_fields missing"), + }; + assert_eq!(min_fields, vec!["id".to_string()]); + } + + #[test] + fn min_max_omitted_when_only_other_columns() { + let mut t = table("Blob", vec![col("payload", "bytea", Scalar::Other)]); + t.public_aggregations = true; + let registry = build(&model(vec![t]), Role::Public); + assert_eq!( + ( + registry.get("Blob_min_fields").is_none(), + registry.get("Blob_max_fields").is_none() + ), + (true, true) + ); + } +} diff --git a/packages/cli/src/serve/gql/types.rs b/packages/cli/src/serve/gql/types.rs new file mode 100644 index 0000000000..a23115f6a8 --- /dev/null +++ b/packages/cli/src/serve/gql/types.rs @@ -0,0 +1,187 @@ +//! In-memory GraphQL type system for `envio serve`, mirroring the schema +//! Hasura generates. One registry is built per role; it drives validation, +//! planning and introspection alike. + +use std::collections::BTreeMap; + +#[derive(Clone, Debug, PartialEq)] +pub enum TypeRef { + Named(String), + NonNull(Box), + List(Box), +} + +impl TypeRef { + pub fn named(name: &str) -> TypeRef { + TypeRef::Named(name.to_string()) + } + pub fn non_null(inner: TypeRef) -> TypeRef { + TypeRef::NonNull(Box::new(inner)) + } + pub fn list(inner: TypeRef) -> TypeRef { + TypeRef::List(Box::new(inner)) + } + /// [T!]! — the common Hasura list shape. + pub fn non_null_list_of_non_null(name: &str) -> TypeRef { + TypeRef::non_null(TypeRef::list(TypeRef::non_null(TypeRef::named(name)))) + } + + pub fn base_name(&self) -> &str { + match self { + TypeRef::Named(n) => n, + TypeRef::NonNull(inner) | TypeRef::List(inner) => inner.base_name(), + } + } + + pub fn is_non_null(&self) -> bool { + matches!(self, TypeRef::NonNull(_)) + } + + /// Type name as printed in Hasura error messages, e.g. `[User_order_by!]`. + pub fn display(&self) -> String { + match self { + TypeRef::Named(n) => n.clone(), + TypeRef::NonNull(inner) => format!("{}!", inner.display()), + TypeRef::List(inner) => format!("[{}]", inner.display()), + } + } +} + +/// What a field means to the planner/executor. +#[derive(Clone, Debug)] +pub enum FieldKind { + /// Root list field: `User(...): [User!]!` + SelectMany { table: String }, + /// Root single-row field: `User_by_pk(id: ...)` + SelectByPk { table: String }, + /// Root aggregate field: `User_aggregate(...)` + SelectAggregate { table: String }, + /// Subscription streaming field: `User_stream(...)` + SelectStream { table: String }, + /// Table column. + Column { column: String }, + /// Object relationship to another table. + ObjectRel { rel: String }, + /// Array relationship to another table. + ArrayRel { rel: String }, + /// Array relationship aggregate: `tokens_aggregate`. + ArrayRelAggregate { rel: String }, + /// `_aggregate.aggregate` + AggregateBody, + /// `_aggregate.nodes` + AggregateNodes, + /// `count` inside `_aggregate_fields` + AggregateCount, + /// `sum`/`avg`/`min`/... inside `_aggregate_fields` + AggregateOp { op: String }, + /// A column inside `__fields` + AggregateOpColumn { op: String, column: String }, + /// Introspection: `__schema`, `__type`; also meta-object fields. + Introspection, +} + +#[derive(Clone, Debug)] +pub struct InputValueDef { + pub name: String, + pub description: Option, + pub ty: TypeRef, + /// GraphQL-literal-syntax default value, as introspection prints it. + pub default_value: Option, +} + +impl InputValueDef { + pub fn new(name: &str, description: Option<&str>, ty: TypeRef) -> InputValueDef { + InputValueDef { + name: name.to_string(), + description: description.map(|s| s.to_string()), + ty, + default_value: None, + } + } +} + +#[derive(Clone, Debug)] +pub struct FieldDef { + pub name: String, + pub description: Option, + pub args: Vec, + pub ty: TypeRef, + pub kind: FieldKind, +} + +#[derive(Clone, Debug)] +pub struct EnumValueDef { + pub name: String, + pub description: Option, +} + +#[derive(Clone, Debug)] +pub enum TypeDef { + Scalar { + name: String, + description: Option, + }, + Object { + name: String, + description: Option, + fields: Vec, + }, + InputObject { + name: String, + description: Option, + fields: Vec, + }, + Enum { + name: String, + description: Option, + values: Vec, + }, +} + +impl TypeDef { + pub fn name(&self) -> &str { + match self { + TypeDef::Scalar { name, .. } + | TypeDef::Object { name, .. } + | TypeDef::InputObject { name, .. } + | TypeDef::Enum { name, .. } => name, + } + } + + // Field vectors are name-sorted by construction (schema_build sorts + // every object/input-object's fields), so lookups binary-search. + pub fn field(&self, name: &str) -> Option<&FieldDef> { + match self { + TypeDef::Object { fields, .. } => fields + .binary_search_by(|f| f.name.as_str().cmp(name)) + .ok() + .map(|i| &fields[i]), + _ => None, + } + } + + pub fn input_field(&self, name: &str) -> Option<&InputValueDef> { + match self { + TypeDef::InputObject { fields, .. } => fields + .binary_search_by(|f| f.name.as_str().cmp(name)) + .ok() + .map(|i| &fields[i]), + _ => None, + } + } +} + +/// A role's full GraphQL schema. Types are kept sorted by name (Hasura's +/// introspection ordering). +pub struct Registry { + pub types: BTreeMap, + pub query_root: String, + pub mutation_root: Option, + pub subscription_root: String, +} + +impl Registry { + pub fn get(&self, name: &str) -> Option<&TypeDef> { + self.types.get(name) + } +} diff --git a/packages/cli/src/serve/http.rs b/packages/cli/src/serve/http.rs new file mode 100644 index 0000000000..c48e104563 --- /dev/null +++ b/packages/cli/src/serve/http.rs @@ -0,0 +1,650 @@ +//! HTTP server: POST /v1/graphql (+ health endpoints and the WebSocket +//! upgrade for subscriptions). + +use super::exec::{self, GraphQLRequest, Schemas}; +use super::gql::schema_build::Role; +use super::ServeState; +use anyhow::{anyhow, Context}; +use axum::body::Bytes; +use axum::extract::{DefaultBodyLimit, State}; +use axum::http::{HeaderMap, StatusCode}; +use axum::response::IntoResponse; +use axum::routing::{get, post}; +use axum::Router; +use std::net::SocketAddr; +use std::sync::Arc; +use std::time::Duration; + +#[derive(Clone)] +pub struct AppState { + pub serve: Arc, + pub schemas: Arc, + /// Flips to true on the shutdown signal so long-lived WebSocket + /// connections can close cleanly instead of being dropped at the drain + /// timeout. + pub shutdown: tokio::sync::watch::Receiver, + /// Admission controls shared by every WebSocket connection handled by + /// this server instance. + pub ws_connection_slots: Arc, + pub ws_operation_slots: Arc, + pub ws_poll_slots: Arc, + /// Exact live-query cohorts shared across all sockets. A cohort owns one + /// poll loop and fans changed results out to every matching subscriber. + pub(crate) live_queries: super::ws::LiveQueryRegistry, +} + +/// How long in-flight requests get to finish after a shutdown signal +/// before the process exits anyway (open WebSocket subscriptions never +/// close on their own, so an unbounded drain would hang forever). Sits +/// just under Kubernetes' default 30s termination grace period so slow +/// but legitimate queries get most of the available window. +const SHUTDOWN_DRAIN_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(25); +/// Keep the historical axum behavior, but make it an intentional API and +/// security boundary rather than inheriting a dependency default. +const GRAPHQL_HTTP_BODY_LIMIT: usize = 2 * 1024 * 1024; + +pub async fn serve( + state: Arc, + host: &str, + port: u16, + shutdown: impl std::future::Future + Send + 'static, +) -> anyhow::Result<()> { + let schemas = Arc::new(Schemas::build(&state.model)); + let (shutdown_tx, shutdown_rx) = tokio::sync::watch::channel(false); + let app_state = AppState { + ws_connection_slots: Arc::new(tokio::sync::Semaphore::new(state.ws_max_connections)), + ws_operation_slots: Arc::new(tokio::sync::Semaphore::new(state.ws_max_operations)), + ws_poll_slots: Arc::new(tokio::sync::Semaphore::new(state.ws_max_concurrent_polls)), + live_queries: super::ws::LiveQueryRegistry::default(), + serve: state, + schemas, + shutdown: shutdown_rx.clone(), + }; + + let app = Router::new() + .route( + "/v1/graphql", + post(graphql_handler) + .get(ws_or_get_handler) + .layer(DefaultBodyLimit::max(GRAPHQL_HTTP_BODY_LIMIT)), + ) + .route("/healthz", get(healthz)) + .route("/hasura/healthz", get(healthz)) + .route("/livez", get(livez)) + .with_state(app_state) + .into_make_service(); + + let (addr, listener) = bind_listener(host, port)?; + tracing::info!("envio serve: GraphQL API at http://{addr}/v1/graphql"); + + tokio::spawn(async move { + shutdown.await; + let _ = shutdown_tx.send(true); + }); + let mut graceful_rx = shutdown_rx.clone(); + let mut drain_rx = shutdown_rx; + tokio::select! { + r = axum::serve(listener, app).with_graceful_shutdown(async move { + let _ = graceful_rx.changed().await; + }) => { r?; } + _ = async move { + let _ = drain_rx.changed().await; + tokio::time::sleep(SHUTDOWN_DRAIN_TIMEOUT).await; + } => { + tracing::warn!("envio serve: drain timeout reached, closing remaining connections"); + } + } + Ok(()) +} + +fn bind_listener(host: &str, port: u16) -> anyhow::Result<(SocketAddr, tokio::net::TcpListener)> { + let addr: SocketAddr = format!("{host}:{port}").parse().map_err(|_| { + anyhow!( + "Invalid serve host \"{host}\". Use an IP address such as 127.0.0.1 \ + (local only) or 0.0.0.0 (all interfaces)." + ) + })?; + match bind_with_keepalive(addr) { + Ok(listener) => Ok((addr, listener)), + Err(error) if error.chain().any(|cause| { + cause + .downcast_ref::() + .is_some_and(|io| io.kind() == std::io::ErrorKind::AddrInUse) + }) => { + let alternative = if port == u16::MAX { 8081 } else { port + 1 }; + Err(anyhow!( + "Port {port} is already in use on {host}, so envio serve could not start.\n\ + To fix this either:\n \ + 1. Stop the process using the port: lsof -ti :{port} | xargs kill\n \ + 2. Use a different port: envio serve --port {alternative}\n \ + or: ENVIO_SERVE_PORT={alternative} envio serve" + )) + } + Err(error) => Err(error).context(format!( + "Failed binding envio serve to {addr}. Check that the host is available and the process has permission to listen on port {port}" + )), + } +} + +/// How long a connection can sit idle before the kernel starts probing it, +/// and how it probes -- tuned well below most orchestrators' idle-reap +/// windows so a half-open connection (peer vanished without a FIN/RST, e.g. +/// power loss or a hard network partition) gets reclaimed in well under a +/// minute instead of Linux's multi-hour default. +const TCP_KEEPALIVE_IDLE: Duration = Duration::from_secs(30); +const TCP_KEEPALIVE_INTERVAL: Duration = Duration::from_secs(10); +const TCP_KEEPALIVE_RETRIES: u32 = 3; + +/// Binds the listening socket with SO_KEEPALIVE (and tuned probe timing +/// where the platform supports it) set before `listen()`, so accepted +/// connections inherit it -- a backstop under the WS-level ping/pong dead- +/// client detection for peers that vanish at the network level (ping/pong +/// only catches an application that stops reading on an otherwise-live +/// connection). +fn bind_with_keepalive(addr: SocketAddr) -> anyhow::Result { + use socket2::{Domain, Socket, TcpKeepalive, Type}; + + let socket = Socket::new(Domain::for_address(addr), Type::STREAM, None)?; + socket.set_nonblocking(true)?; + socket.set_reuse_address(true)?; + let keepalive = TcpKeepalive::new() + .with_time(TCP_KEEPALIVE_IDLE) + .with_interval(TCP_KEEPALIVE_INTERVAL); + #[cfg(not(any(target_os = "windows", target_os = "openbsd", target_os = "redox")))] + let keepalive = keepalive.with_retries(TCP_KEEPALIVE_RETRIES); + socket.set_tcp_keepalive(&keepalive)?; + socket.bind(&addr.into())?; + socket.listen(1024)?; + let std_listener: std::net::TcpListener = socket.into(); + Ok(tokio::net::TcpListener::from_std(std_listener)?) +} + +/// Readiness-style probe: verifies a pooled connection can run a query, so +/// orchestrators see Postgres outages instead of a permanently-green +/// process. Bounded independently of the pool's own wait timeout (via +/// ENVIO_SERVE_HEALTHZ_TIMEOUT_MS) so the probe answers fast even when the +/// pool is exhausted or the DB is frozen. Use `/livez` instead for a +/// process-only liveness check that doesn't depend on Postgres at all. +async fn healthz(State(state): State) -> impl IntoResponse { + let probe = async { + let client = state.serve.pool.get().await.ok()?; + client.simple_query("SELECT 1").await.ok() + }; + match tokio::time::timeout(state.serve.healthz_timeout, probe).await { + Ok(Some(_)) => (StatusCode::OK, "OK"), + _ => (StatusCode::INTERNAL_SERVER_ERROR, "ERROR"), + } +} + +/// Liveness-style probe: the process is up and serving HTTP, full stop -- +/// no Postgres round-trip. Orchestrators use this for "should this +/// container be restarted" (a slow/unreachable Postgres shouldn't trigger +/// a restart, since restarting the process doesn't fix Postgres and +/// startup retry already handles a not-yet-ready database) while `/healthz` +/// answers "should this instance receive traffic". +async fn livez() -> impl IntoResponse { + (StatusCode::OK, "OK") +} + +/// Compares a client-supplied admin secret without leaking match length +/// through timing. A length mismatch still rejects (length isn't secret), +/// but equal-length comparison never early-exits on content. +pub fn admin_secret_matches(provided: &str, expected: &str) -> bool { + use subtle::ConstantTimeEq; + provided.as_bytes().ct_eq(expected.as_bytes()).into() +} + +/// Resolve the request's role from header values, mirroring Hasura: +/// - correct admin secret -> admin (or the role named in X-Hasura-Role; +/// a role that isn't in the metadata — anything but `admin`/`public` +/// here — is an access-denied error, like Hasura v2) +/// - wrong admin secret -> HTTP 200 with an access-denied GraphQL error +/// (verified live — Hasura never uses 401 for this) +/// - no secret -> the unauthorized role (public) +pub fn resolve_role_values( + provided_secret: Option<&str>, + requested_role: Option<&str>, + admin_secret: &str, +) -> Result { + match provided_secret { + None => Ok(Role::Public), + Some(s) if admin_secret_matches(s, admin_secret) => match requested_role { + None | Some("admin") => Ok(Role::Admin), + Some("public") => Ok(Role::Public), + Some(other) => { + tracing::debug!(role = other, "rejecting request for unknown x-hasura-role"); + Err(exec::error::GraphQLError { + message: "your requested role is not in allowed roles".to_string(), + path: "$".to_string(), + code: exec::error::CODE_ACCESS_DENIED, + status: 200, + }) + } + }, + Some(_) => { + tracing::debug!("rejecting request with wrong x-hasura-admin-secret"); + Err(exec::error::GraphQLError::access_denied()) + } + } +} + +pub fn resolve_role( + headers: &HeaderMap, + admin_secret: &str, +) -> Result { + resolve_role_values( + headers + .get("x-hasura-admin-secret") + .and_then(|v| v.to_str().ok()), + headers.get("x-hasura-role").and_then(|v| v.to_str().ok()), + admin_secret, + ) +} + +async fn graphql_handler( + State(state): State, + headers: HeaderMap, + body: Bytes, +) -> impl IntoResponse { + let role = match resolve_role(&headers, &state.serve.admin_secret) { + Ok(role) => role, + Err(e) => { + return ( + StatusCode::from_u16(e.status).unwrap_or(StatusCode::UNAUTHORIZED), + [("content-type", "application/json; charset=utf-8")], + e.response_body().to_string(), + ); + } + }; + + let request = match decode_request_body(&body) { + Ok(r) => r, + Err(e) => { + return ( + StatusCode::from_u16(e.status).unwrap_or(StatusCode::OK), + [("content-type", "application/json; charset=utf-8")], + e.response_body().to_string(), + ); + } + }; + + let (status, body) = + exec::execute_query_request(&state.serve, &state.schemas, role, &request).await; + ( + StatusCode::from_u16(status).unwrap_or(StatusCode::OK), + [("content-type", "application/json; charset=utf-8")], + body, + ) +} + +/// aeson's name for a JSON value's kind, as it appears in Hasura's +/// parse-failed messages. +fn aeson_kind(v: &serde_json::Value) -> &'static str { + match v { + serde_json::Value::Null => "Null", + serde_json::Value::Bool(_) => "Boolean", + serde_json::Value::Number(_) => "Number", + serde_json::Value::String(_) => "String", + serde_json::Value::Array(_) => "Array", + serde_json::Value::Object(_) => "Object", + } +} + +/// Decodes the POST body with Hasura's exact error shapes: invalid UTF-8 +/// and malformed JSON are `invalid-json`; structurally wrong GQLReq +/// payloads are `parse-failed` with aeson-style messages. +fn decode_request_body(body: &[u8]) -> Result { + use exec::error::GraphQLError; + + let invalid_json = |message: String| GraphQLError { + message, + path: "$".to_string(), + code: "invalid-json", + status: 200, + }; + let parse_failed = |path: &str, message: String| GraphQLError { + message, + path: path.to_string(), + code: exec::error::CODE_PARSE_FAILED, + status: 200, + }; + + let text = + match std::str::from_utf8(body) { + Ok(t) => t, + Err(_) => return Err(invalid_json( + "Cannot decode input: Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream" + .to_string(), + )), + }; + + let (value, number_originals) = + match exec::validate::json_numbers::parse_value_preserving_numbers(text) { + Ok(v) => v, + // Lone-surrogate escapes decode to invalid UTF-8 in Hasura's + // text pipeline; it reports them as a UTF-8 decoding failure. + // serde_json calls the same condition "unexpected end of hex + // escape" (no continuation escape after the lead surrogate). + Err(e) + if e.to_string().contains("surrogate") + || e.to_string().contains("unexpected end of hex escape") => + { + return Err(invalid_json( + "Cannot decode input: Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream" + .to_string(), + )) + } + Err(e) => return Err(invalid_json(e.to_string())), + }; + + let obj = match &value { + serde_json::Value::Object(o) => o, + other => { + return Err(parse_failed( + "$", + format!( + "parsing Hasura.GraphQL.Transport.HTTP.Protocol.GQLReq(GQLReq) failed, expected Object, but encountered {}", + aeson_kind(other) + ), + )) + } + }; + + let query = match obj.get("query") { + None => { + return Err(parse_failed( + "$", + "parsing Hasura.GraphQL.Transport.HTTP.Protocol.GQLReq(GQLReq) failed, key \"query\" not found" + .to_string(), + )) + } + Some(serde_json::Value::String(s)) => s.clone(), + Some(other) => { + return Err(parse_failed( + "$.query", + format!( + "parsing Text failed, expected String, but encountered {}", + aeson_kind(other) + ), + )) + } + }; + + let operation_name = match obj.get("operationName") { + None | Some(serde_json::Value::Null) => None, + Some(serde_json::Value::String(s)) => Some(s.clone()), + Some(other) => { + return Err(parse_failed( + "$.operationName", + format!( + "parsing Text failed, expected String, but encountered {}", + aeson_kind(other) + ), + )) + } + }; + + let variables = match obj.get("variables") { + None => None, + Some(v @ (serde_json::Value::Object(_) | serde_json::Value::Null)) => Some(v.clone()), + Some(other) => { + return Err(parse_failed( + "$.variables", + format!( + "parsing HashMap failed, expected Object, but encountered {}", + aeson_kind(other) + ), + )) + } + }; + + // Variable numbers that don't round-trip through serde_json's f64 + // (e.g. >19-digit integers) are re-read from the raw body text with + // sentinel substitution so their exact text reaches SQL parameters, + // as Hasura's arbitrary-precision Scientific does. + let variable_number_originals = if matches!(variables, Some(serde_json::Value::Object(_))) { + number_originals + } else { + Default::default() + }; + + Ok(GraphQLRequest { + query: Some(query), + variables, + operation_name, + variable_number_originals, + }) +} + +/// GET /v1/graphql serves the WebSocket upgrade (subscriptions). +async fn ws_or_get_handler( + State(state): State, + headers: HeaderMap, + ws: axum::extract::ws::WebSocketUpgrade, +) -> axum::response::Response { + super::ws::handle_upgrade(state, headers, ws) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn occupied_port_error_has_recovery_commands() { + let occupied = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + let port = occupied.local_addr().unwrap().port(); + let error = bind_listener("127.0.0.1", port).unwrap_err().to_string(); + assert!(error.contains(&format!("Port {port} is already in use"))); + assert!(error.contains(&format!("lsof -ti :{port} | xargs kill"))); + assert!(error.contains(&format!("envio serve --port {}", port + 1))); + assert!(error.contains(&format!("ENVIO_SERVE_PORT={}", port + 1))); + } + + #[test] + fn invalid_host_error_names_valid_alternatives() { + let error = bind_listener("not a socket address", 8080) + .unwrap_err() + .to_string(); + assert!(error.contains("Invalid serve host \"not a socket address\"")); + assert!(error.contains("127.0.0.1")); + assert!(error.contains("0.0.0.0")); + } + + // Error shapes mirror Hasura's, matching the em-* error-matrix corpus + // (e.g. em-body-lone-surrogate-in-query pins the invalid-json path). + #[test] + fn request_body_decoding_errors() { + let decode = |body: &str| { + decode_request_body(body.as_bytes()) + .map(|_| unreachable!("expected a decode error for {body:?}")) + .unwrap_err() + }; + let shape = |e: exec::error::GraphQLError| (e.message, e.path, e.code, e.status); + assert_eq!( + [ + decode("not json"), + decode("[1,2]"), + decode("\"query\""), + decode("42"), + decode("{}"), + decode("{\"query\": 5}"), + decode("{\"query\": \"{ x }\", \"variables\": \"v\"}"), + decode("{\"query\": \"{ x }\", \"variables\": [1]}"), + ] + .map(shape), + [ + ( + "expected ident at line 1 column 2".to_string(), + "$".to_string(), + "invalid-json", + 200 + ), + ( + "parsing Hasura.GraphQL.Transport.HTTP.Protocol.GQLReq(GQLReq) failed, expected Object, but encountered Array".to_string(), + "$".to_string(), + "parse-failed", + 200 + ), + ( + "parsing Hasura.GraphQL.Transport.HTTP.Protocol.GQLReq(GQLReq) failed, expected Object, but encountered String".to_string(), + "$".to_string(), + "parse-failed", + 200 + ), + ( + "parsing Hasura.GraphQL.Transport.HTTP.Protocol.GQLReq(GQLReq) failed, expected Object, but encountered Number".to_string(), + "$".to_string(), + "parse-failed", + 200 + ), + ( + "parsing Hasura.GraphQL.Transport.HTTP.Protocol.GQLReq(GQLReq) failed, key \"query\" not found".to_string(), + "$".to_string(), + "parse-failed", + 200 + ), + ( + "parsing Text failed, expected String, but encountered Number".to_string(), + "$.query".to_string(), + "parse-failed", + 200 + ), + ( + "parsing HashMap failed, expected Object, but encountered String".to_string(), + "$.variables".to_string(), + "parse-failed", + 200 + ), + ( + "parsing HashMap failed, expected Object, but encountered Array".to_string(), + "$.variables".to_string(), + "parse-failed", + 200 + ), + ] + ); + } + + #[test] + fn variable_number_metadata_is_decoder_owned() { + let request = + decode_request_body(br#"{"query":"q","variables":{"big":99999999999999999999999}}"#) + .unwrap(); + let variables = request.variables.as_ref().unwrap(); + let bits = variables["big"].as_f64().unwrap().to_bits(); + assert_eq!( + request + .variable_number_originals + .get(&bits) + .map(String::as_str), + Some("99999999999999999999999") + ); + + let spoofed = decode_request_body( + br#"{"query":"q","variables":{"v":1.5,"\u0001variable number originals":{"4609434218613702656":"999999999999999999"}}}"#, + ) + .unwrap(); + assert!(spoofed.variable_number_originals.is_empty()); + assert!(spoofed + .variables + .unwrap() + .get("\u{1}variable number originals") + .is_some()); + } + + #[test] + fn out_of_f64_range_variable_numbers_are_preserved() { + let request = decode_request_body( + br#"{"query":"query($n: numeric!, $j: jsonb!) { x }","variables":{"n":1e400,"j":{"nested":-9e999}}}"#, + ) + .expect("arbitrary-precision JSON numbers are valid Hasura inputs"); + let variables = request.variables.as_ref().unwrap(); + let n_bits = variables["n"].as_f64().unwrap().to_bits(); + let nested_bits = variables["j"]["nested"].as_f64().unwrap().to_bits(); + assert_eq!( + ( + request + .variable_number_originals + .get(&n_bits) + .map(String::as_str), + request + .variable_number_originals + .get(&nested_bits) + .map(String::as_str), + ), + (Some("1e400"), Some("-9e999")) + ); + + let malformed = + decode_request_body(br#"{"query":"query($n: numeric!) { x }","variables":{"n":1e}}"#) + .err() + .expect("malformed JSON must still be rejected"); + assert_eq!(malformed.code, "invalid-json"); + } + + #[test] + fn admin_secret_comparison() { + assert_eq!( + [ + admin_secret_matches("secret", "secret"), + admin_secret_matches("secreT", "secret"), + admin_secret_matches("secret-longer", "secret"), + admin_secret_matches("", "secret"), + admin_secret_matches("", ""), + ], + [true, false, false, false, true] + ); + } + + #[test] + fn role_resolution() { + let resolve = + |secret: Option<&str>, role: Option<&str>| resolve_role_values(secret, role, "s3cret"); + let tag = |r: Result| match r { + Ok(Role::Admin) => "admin", + Ok(Role::Public) => "public", + Err(_) => "err", + }; + assert_eq!( + [ + resolve(None, None), + resolve(None, Some("admin")), + resolve(Some("s3cret"), None), + resolve(Some("s3cret"), Some("admin")), + resolve(Some("s3cret"), Some("public")), + ] + .map(tag), + ["public", "public", "admin", "admin", "public"] + ); + + let wrong_secret = resolve(Some("nope"), None).unwrap_err(); + assert_eq!( + ( + wrong_secret.message.as_str(), + wrong_secret.code, + wrong_secret.status + ), + ( + "invalid \"x-hasura-admin-secret\"/\"x-hasura-access-key\"", + "access-denied", + 200 + ) + ); + + // A role outside the metadata (only admin/public exist) with a + // valid secret is access-denied, not a silent public downgrade. + let unknown_role = resolve(Some("s3cret"), Some("editor")).unwrap_err(); + assert_eq!( + ( + unknown_role.message.as_str(), + unknown_role.code, + unknown_role.status + ), + ( + "your requested role is not in allowed roles", + "access-denied", + 200 + ) + ); + } +} diff --git a/packages/cli/src/serve/mod.rs b/packages/cli/src/serve/mod.rs new file mode 100644 index 0000000000..423d3799e5 --- /dev/null +++ b/packages/cli/src/serve/mod.rs @@ -0,0 +1,323 @@ +//! `envio serve` — a Hasura-compatible GraphQL server over the indexer's +//! Postgres database. +//! +//! The GraphQL surface mirrors what Hasura exposes after the indexer's +//! `Hasura.res` `trackDatabase` metadata setup: user entity tables plus +//! `raw_events`, `_meta` and `chain_metadata`, a `public` role for +//! unauthenticated requests (row limit + per-table aggregate gating from the +//! same env vars the indexer reads) and an admin role selected by the +//! `X-Hasura-Admin-Secret` header. +//! +//! Column shapes come from live Postgres catalog introspection (like Hasura's +//! own source introspection) so projects created by older envio versions are +//! served faithfully; only the table list and relationships come from +//! `schema.graphql`, resolved through a deliberately minimal `config.yaml` +//! reader that tolerates configs from any envio version >= 2.21.5. + +mod env_config; +mod exec; +mod gql; +mod http; +mod model; +mod pg_catalog; +mod project_schema; +mod ws; + +use crate::cli_args::clap_definitions::ServeArgs; +use crate::project_paths::ParsedProjectPaths; +use anyhow::Context; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; + +static EXTERNAL_SHUTDOWN_REQUESTED: AtomicBool = AtomicBool::new(false); +static EXTERNAL_SHUTDOWN_NOTIFY: std::sync::OnceLock = + std::sync::OnceLock::new(); + +/// Called by the Node host's SIGINT/SIGTERM handlers. `notify_one` retains a +/// permit when the Rust future has not started waiting yet, while the atomic +/// flag makes the request explicit and lets one serve invocation consume it. +pub(crate) fn request_shutdown() { + EXTERNAL_SHUTDOWN_REQUESTED.store(true, Ordering::Release); + EXTERNAL_SHUTDOWN_NOTIFY + .get_or_init(tokio::sync::Notify::new) + .notify_one(); +} + +async fn external_shutdown_signal() { + let notify = EXTERNAL_SHUTDOWN_NOTIFY.get_or_init(tokio::sync::Notify::new); + loop { + if EXTERNAL_SHUTDOWN_REQUESTED.swap(false, Ordering::AcqRel) { + return; + } + notify.notified().await; + } +} + +#[cfg(test)] +mod robustness_tests; +#[cfg(test)] +mod test_support; + +pub struct ServeState { + pub model: model::ServerModel, + pub pool: deadpool_postgres::Pool, + pub admin_secret: String, + /// Client-side bound on a whole operation's execution (every root + /// field's pool wait + prepare + query). The server-side + /// statement_timeout normally fires first; this is the backstop for a + /// Postgres that stopped responding entirely. + pub query_timeout: Option, + /// Bounds the /healthz Postgres probe. + pub healthz_timeout: std::time::Duration, + /// How often idle WebSocket connections get a protocol-level ping; a + /// connection that sends no pong/traffic within 2x this gets closed. + pub ws_ping_interval: std::time::Duration, + /// Maximum time an upgraded socket may wait for connection_init. + pub ws_connection_init_timeout: std::time::Duration, + pub ws_max_connections: usize, + pub ws_max_operations_per_connection: usize, + pub ws_max_operations: usize, + pub ws_max_concurrent_polls: usize, + pub ws_poll_interval: std::time::Duration, + pub ws_max_message_bytes: usize, +} + +pub async fn run(args: &ServeArgs, project_paths: &ParsedProjectPaths) -> anyhow::Result<()> { + init_tracing(); + let env = env_config::ServeEnv::load(project_paths)?; + tracing::info!( + pg_host = %env.pg_host, + pg_port = env.pg_port, + pg_database = %env.pg_database, + pg_schema = %env.pg_schema, + pg_ssl_mode = env.pg_ssl.as_str(), + pool_max_size = env.pool_max_size, + ws_ping_interval_ms = env.ws_ping_interval_ms, + ws_connection_init_timeout_ms = env.ws_connection_init_timeout_ms, + ws_max_connections = env.ws_max_connections, + ws_max_operations_per_connection = env.ws_max_operations_per_connection, + ws_max_operations = env.ws_max_operations, + ws_max_concurrent_polls = env.ws_max_concurrent_polls, + ws_poll_interval_ms = env.ws_poll_interval_ms, + ws_max_message_bytes = env.ws_max_message_bytes, + healthz_timeout_ms = env.healthz_timeout_ms, + startup_retry_budget_ms = env.startup_retry_budget_ms, + query_timeout_ms = env.query_timeout_ms, + "envio serve starting" + ); + + let project_schema = project_schema::ProjectSchema::load(project_paths, &env) + .context("Failed loading schema.graphql")?; + + let pool = env + .make_pg_pool() + .context("Failed creating Postgres pool")?; + + let catalog = tokio::select! { + result = wait_for_pg(&pool, &env.pg_schema, env.startup_retry_budget_ms) => { + result.map_err(|error| postgres_startup_error(&env, error))? + } + _ = shutdown_signal() => return Ok(()), + }; + + let model = model::ServerModel::build(project_schema, catalog, &env)?; + + let state = Arc::new(ServeState { + model, + pool, + admin_secret: env.admin_secret.clone(), + // +5s slack so the server-side statement_timeout (clean SQLSTATE + // 57014 cancellation) wins whenever Postgres is still responsive. + query_timeout: env + .query_timeout_ms + .map(|ms| std::time::Duration::from_millis(ms + 5_000)), + healthz_timeout: std::time::Duration::from_millis(env.healthz_timeout_ms), + ws_ping_interval: std::time::Duration::from_millis(env.ws_ping_interval_ms), + ws_connection_init_timeout: std::time::Duration::from_millis( + env.ws_connection_init_timeout_ms, + ), + ws_max_connections: env.ws_max_connections, + ws_max_operations_per_connection: env.ws_max_operations_per_connection, + ws_max_operations: env.ws_max_operations, + ws_max_concurrent_polls: env.ws_max_concurrent_polls, + ws_poll_interval: std::time::Duration::from_millis(env.ws_poll_interval_ms), + ws_max_message_bytes: env.ws_max_message_bytes, + }); + + http::serve(state, &args.host, args.port, shutdown_signal()).await +} + +/// Structured logging for the serve path only. The rest of the CLI logs via +/// env_logger; that's initialized lazily on the indexing path +/// (evm_hypersync_source), which `envio serve` never reaches, so the two +/// never contend for the global `log` logger. Filtered by RUST_LOG, +/// defaulting to `info` (per-connection/per-operation events are `debug`). +fn init_tracing() { + let filter = tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")); + let _ = tracing_subscriber::fmt().with_env_filter(filter).try_init(); +} + +/// Longest single backoff sleep between startup retry attempts, regardless +/// of how large the total budget is. +const STARTUP_RETRY_MAX_BACKOFF: std::time::Duration = std::time::Duration::from_secs(5); + +/// Retries catalog introspection (the first real Postgres round-trip) with +/// bounded exponential backoff for `budget_ms` total, so a deploy that +/// starts `envio serve` before Postgres is accepting connections doesn't +/// crash-loop -- it just waits. Only retries connectivity failures +/// (connection refused, DNS, timeout); a Postgres that responds with a real +/// error (bad credentials, missing database) fails immediately instead of +/// burning the whole budget on an error retrying can't fix. `budget_ms == +/// 0` disables retrying entirely (fail on the first attempt). +async fn wait_for_pg( + pool: &deadpool_postgres::Pool, + pg_schema: &str, + budget_ms: u64, +) -> anyhow::Result { + let start = std::time::Instant::now(); + let budget = std::time::Duration::from_millis(budget_ms); + let mut backoff = std::time::Duration::from_millis(500); + let mut attempt: u32 = 0; + loop { + match pg_catalog::introspect(pool, pg_schema).await { + Ok(catalog) => return Ok(catalog), + Err(e) + if budget_ms > 0 && is_pg_unreachable(&e) && start.elapsed() + backoff < budget => + { + attempt += 1; + tracing::warn!( + "Postgres not reachable yet (attempt {attempt}): {e:#}. Retrying in {:.1}s...", + backoff.as_secs_f32() + ); + tokio::time::sleep(backoff).await; + backoff = std::cmp::min(backoff * 2, STARTUP_RETRY_MAX_BACKOFF); + } + Err(e) => return Err(e), + } + } +} + +/// True for connection-level failures (refused/reset/DNS/timeout) where +/// Postgres never actually answered. False once Postgres has responded +/// with a backend error (auth failure, unknown database, ...) -- those are +/// real config problems that retrying the same connection attempt cannot +/// fix. +fn is_pg_unreachable(err: &anyhow::Error) -> bool { + for cause in err.chain() { + if let Some(pool_err) = cause.downcast_ref::() { + return match pool_err { + deadpool_postgres::PoolError::Backend(e) => e.as_db_error().is_none(), + deadpool_postgres::PoolError::Timeout(_) => true, + _ => false, + }; + } + if let Some(e) = cause.downcast_ref::() { + return e.as_db_error().is_none(); + } + } + false +} + +fn postgres_db_error(err: &anyhow::Error) -> Option<&tokio_postgres::error::DbError> { + for cause in err.chain() { + if let Some(deadpool_postgres::PoolError::Backend(error)) = + cause.downcast_ref::() + { + if let Some(db_error) = error.as_db_error() { + return Some(db_error); + } + } + if let Some(error) = cause.downcast_ref::() { + if let Some(db_error) = error.as_db_error() { + return Some(db_error); + } + } + } + None +} + +/// Adds recovery steps to startup failures without exposing the configured +/// password. The original driver chain remains under `Details` for debugging. +fn postgres_startup_error(env: &env_config::ServeEnv, error: anyhow::Error) -> anyhow::Error { + let endpoint = format!("{}:{}/{}", env.pg_host, env.pg_port, env.pg_database); + let details = format!("{error:#}"); + + if is_pg_unreachable(&error) { + return anyhow::anyhow!( + "Cannot connect to PostgreSQL at {endpoint}.\n\ + Make sure PostgreSQL is running and reachable, then check \ + ENVIO_PG_HOST, ENVIO_PG_PORT, ENVIO_PG_DATABASE, ENVIO_PG_USER, \ + ENVIO_PG_PASSWORD, and ENVIO_PG_SSL_MODE.\n\ + Details: {details}" + ); + } + + if let Some(db_error) = postgres_db_error(&error) { + match db_error.code().code() { + "28P01" => { + return anyhow::anyhow!( + "PostgreSQL rejected the credentials for user \"{}\" at {endpoint}.\n\ + Check ENVIO_PG_USER and ENVIO_PG_PASSWORD.\n\ + Details: {details}", + env.pg_user + ); + } + "3D000" => { + return anyhow::anyhow!( + "PostgreSQL database \"{}\" does not exist at {}:{}.\n\ + Create the database or set ENVIO_PG_DATABASE to an existing one.\n\ + Details: {details}", + env.pg_database, + env.pg_host, + env.pg_port + ); + } + "42501" => { + return anyhow::anyhow!( + "PostgreSQL user \"{}\" cannot inspect schema \"{}\" at {endpoint}.\n\ + Grant the user access to that schema or set ENVIO_PG_USER to a role with access.\n\ + Details: {details}", + env.pg_user, + env.pg_schema + ); + } + _ => {} + } + } + + anyhow::anyhow!( + "Failed inspecting PostgreSQL schema \"{}\" at {endpoint}.\n\ + Check ENVIO_PG_SCHEMA and the PostgreSQL user's schema permissions.\n\ + Details: {details}", + env.pg_schema + ) +} + +/// Resolves on SIGTERM or Ctrl-C so deploys drain in-flight requests +/// instead of hard-dropping them. +async fn shutdown_signal() { + let ctrl_c = tokio::signal::ctrl_c(); + #[cfg(unix)] + { + let mut term = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) + .expect("failed installing SIGTERM handler"); + tokio::select! { + _ = ctrl_c => {} + _ = term.recv() => {} + _ = external_shutdown_signal() => {} + } + } + #[cfg(not(unix))] + { + tokio::select! { + _ = ctrl_c => {} + _ = external_shutdown_signal() => {} + } + } + // If both the host bridge and Tokio observe the same signal, the Tokio + // branch may win the race. Do not let the host's duplicate notification + // leak into a later serve invocation in the same process. + EXTERNAL_SHUTDOWN_REQUESTED.store(false, Ordering::Release); + tracing::info!("shutdown signal received, draining connections"); +} diff --git a/packages/cli/src/serve/model.rs b/packages/cli/src/serve/model.rs new file mode 100644 index 0000000000..017eefdd9e --- /dev/null +++ b/packages/cli/src/serve/model.rs @@ -0,0 +1,666 @@ +//! The server model: which relations are exposed, under which GraphQL +//! names, with which columns and relationships — the union of what Hasura +//! metadata (as applied by the indexer) and Postgres introspection produce. + +use super::env_config::ServeEnv; +use super::pg_catalog::{Catalog, RelationKind}; +use super::project_schema::ProjectSchema; +use crate::config_parsing::field_types::to_snake_case; +use anyhow::anyhow; +use std::collections::HashMap; + +/// GraphQL scalar names as Hasura assigns them per Postgres type. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum Scalar { + String, + Int, + Float, + Boolean, + Bigint, + Numeric, + Float8, + Timestamptz, + Timestamp, + Date, + Jsonb, + Json, + Smallint, + /// A Postgres enum type, exposed by Hasura as an opaque scalar named + /// after the pg type (e.g. `accounttype`). + PgEnum, + /// Fallback for pg types we don't specially handle; exposed under the + /// pg type name like Hasura does. + Other, +} + +impl Scalar { + pub fn from_pg_type(pg_type: &str, is_enum: bool) -> Scalar { + if is_enum { + return Scalar::PgEnum; + } + match pg_type { + "text" | "varchar" | "bpchar" | "name" | "citext" => Scalar::String, + "int4" => Scalar::Int, + "int2" => Scalar::Smallint, + "int8" => Scalar::Bigint, + "float4" => Scalar::Float, + "float8" => Scalar::Float8, + "numeric" => Scalar::Numeric, + "bool" => Scalar::Boolean, + "timestamptz" => Scalar::Timestamptz, + "timestamp" => Scalar::Timestamp, + "date" => Scalar::Date, + "jsonb" => Scalar::Jsonb, + "json" => Scalar::Json, + _ => Scalar::Other, + } + } + + /// The GraphQL type name for this scalar on a column of `pg_type`. + pub fn gql_name(&self, pg_type: &str) -> String { + match self { + Scalar::String => "String".to_string(), + Scalar::Int => "Int".to_string(), + Scalar::Float => "Float".to_string(), + Scalar::Boolean => "Boolean".to_string(), + Scalar::Bigint => "bigint".to_string(), + Scalar::Numeric => "numeric".to_string(), + Scalar::Float8 => "float8".to_string(), + Scalar::Timestamptz => "timestamptz".to_string(), + Scalar::Timestamp => "timestamp".to_string(), + Scalar::Date => "date".to_string(), + Scalar::Jsonb => "jsonb".to_string(), + Scalar::Json => "json".to_string(), + Scalar::Smallint => "smallint".to_string(), + Scalar::PgEnum | Scalar::Other => pg_type.to_string(), + } + } + + /// Whether Hasura's STRINGIFY_NUMERIC_TYPES turns bare column values of + /// this scalar into JSON strings. + pub fn stringified(&self) -> bool { + matches!(self, Scalar::Bigint | Scalar::Numeric | Scalar::Float8) + } + + /// Whether min/max/sum/avg-style numeric aggregates exist for it. + pub fn is_numeric(&self) -> bool { + matches!( + self, + Scalar::Int + | Scalar::Smallint + | Scalar::Float + | Scalar::Bigint + | Scalar::Numeric + | Scalar::Float8 + ) + } +} + +#[derive(Clone)] +pub struct Column { + /// GraphQL field name (Hasura custom column name when renamed). + pub api_name: String, + /// Actual database column name. + pub db_name: String, + pub pg_type: String, + /// Namespace owning `pg_type`; kept separate because GraphQL exposes + /// the bare type name while SQL casts must qualify custom types. + pub pg_type_schema: String, + pub scalar: Scalar, + pub is_array: bool, + pub nullable: bool, + pub description: Option, +} + +pub struct ObjectRelationship { + pub name: String, + /// db column on this table joined to remote "id" + pub local_db_column: String, + pub remote_table: String, +} + +pub struct ArrayRelationship { + pub name: String, + pub remote_table: String, + /// db column on the remote table joined to this table's "id" + pub remote_db_column: String, +} + +pub struct Table { + pub name: String, + pub kind: RelationKind, + pub description: Option, + pub columns: Vec, + pub primary_key: Vec, + pub object_relationships: Vec, + pub array_relationships: Vec, + /// Tracked-with-select-permission tables are visible to the public + /// role; effect-cache tables are tracked without permissions and are + /// admin-only. + pub admin_only: bool, + /// allow_aggregations for the public role. + pub public_aggregations: bool, +} + +impl Table { + pub fn column_by_api_name(&self, name: &str) -> Option<&Column> { + self.columns.iter().find(|c| c.api_name == name) + } +} + +/// Resolves a GraphQL field name to its db column, trying the original name +/// first and then Table.res's `column_name_format` snake_case rewrite -- +/// column_name_format can rename either scalar fields or the `_id` suffix +/// entity-ref columns, so a renamed column may appear under either form. +/// `suffix` (e.g. "_id" for entity-reference columns) is appended after the +/// snake-casing, matching how Table.res derives the column name. +fn resolve_db_column<'a>( + field_name: &str, + suffix: &str, + columns: impl Iterator + Clone, +) -> Option { + [ + format!("{field_name}{suffix}"), + format!("{}{suffix}", to_snake_case(field_name)), + ] + .into_iter() + .find(|db| columns.clone().any(|c| &c.name == db)) +} + +pub struct ServerModel { + /// Exposed tables in Hasura's root-field ordering (sorted by name). + pub tables: Vec
, + pub pg_schema: String, + pub response_limit: Option, +} + +impl ServerModel { + pub fn table(&self, name: &str) -> Option<&Table> { + self.tables + .binary_search_by(|t| t.name.as_str().cmp(name)) + .ok() + .map(|i| &self.tables[i]) + } + + pub fn build( + project: ProjectSchema, + catalog: Catalog, + env: &ServeEnv, + ) -> anyhow::Result { + let mut tables: Vec
= Vec::new(); + + let internal_exposed = ["raw_events", "_meta", "chain_metadata"]; + for name in internal_exposed { + if let Some(rel) = catalog.relations.get(name) { + tables.push(Table { + name: rel.name.clone(), + kind: rel.kind, + description: None, + columns: rel + .columns + .iter() + .map(|c| Column { + api_name: c.name.clone(), + db_name: c.name.clone(), + pg_type: c.pg_type.clone(), + pg_type_schema: c.pg_type_schema.clone(), + scalar: Scalar::from_pg_type(&c.pg_type, c.is_enum), + is_array: c.is_array, + nullable: c.nullable, + description: None, + }) + .collect(), + primary_key: rel.primary_key.clone(), + object_relationships: vec![], + array_relationships: vec![], + admin_only: false, + public_aggregations: env.aggregate_entities.contains(&name.to_string()), + }); + } + } + + let mut skipped_entities: Vec<&str> = Vec::new(); + for entity in &project.entities { + let Some(rel) = catalog.relations.get(&entity.name) else { + // Entity present in schema.graphql but not migrated into the + // DB — Hasura tracking would have failed for it; skip. + skipped_entities.push(&entity.name); + continue; + }; + + // Fields that are entity references (object relationships) are + // stored as `_id` columns; their GraphQL column name is + // also `_id` (Table.res getApiFieldName), while the db + // column may additionally be snake_cased. Hasura never applies + // the relationship field's own description to this underlying + // fk column (Hasura.res's makeColumnConfigs only sets comments + // for plain Table.Field entries, never entity-reference + // fields) — pinned by the `gravatar_id` case in + // introspection-descriptions, so this stays `None` here. + let mut api_by_db: HashMap)> = HashMap::new(); + for rel_def in &entity.object_relationships { + let api = format!("{}_id", rel_def.field_name); + if let Some(db) = resolve_db_column(&rel_def.field_name, "_id", rel.columns.iter()) + { + api_by_db.insert(db, (api, None)); + } + } + // Every db-backed field maps to a column named either exactly + // like the field (`column_name_format: original`) or its + // snake_case (`column_name_format: snake_case`); the api name is + // always the original field name, matching Table.res's + // getApiFieldName / Hasura.res's custom_name renames. + for field in &entity.scalar_fields { + if let Some(db) = resolve_db_column(&field.name, "", rel.columns.iter()) { + api_by_db + .entry(db) + .or_insert((field.name.clone(), field.description.clone())); + } + } + + let columns = rel + .columns + .iter() + .map(|c| { + let (api_name, description) = api_by_db + .get(&c.name) + .cloned() + .unwrap_or((c.name.clone(), None)); + Column { + api_name, + db_name: c.name.clone(), + pg_type: c.pg_type.clone(), + pg_type_schema: c.pg_type_schema.clone(), + scalar: Scalar::from_pg_type(&c.pg_type, c.is_enum), + is_array: c.is_array, + nullable: c.nullable, + description, + } + }) + .collect::>(); + + let object_relationships = entity + .object_relationships + .iter() + .filter_map(|r| { + let db_col = columns + .iter() + .find(|c| c.api_name == format!("{}_id", r.field_name))? + .db_name + .clone(); + if !catalog.relations.contains_key(&r.remote_entity) { + return None; + } + Some(ObjectRelationship { + name: r.field_name.clone(), + local_db_column: db_col, + remote_table: r.remote_entity.clone(), + }) + }) + .collect(); + + let array_relationships = entity + .array_relationships + .iter() + .filter_map(|r| { + let remote_entity = project + .entities + .iter() + .find(|e| e.name == r.remote_entity)?; + let remote_rel = catalog.relations.get(&r.remote_entity)?; + // Resolve the remote field to its db column, mirroring + // Schema.getDerivedFromPgFieldName: entity-ref fields + // get the _id suffix, scalar (ID/String) fields don't. + let is_entity_ref = remote_entity + .object_relationships + .iter() + .any(|or| or.field_name == r.remote_field); + let suffix = if is_entity_ref { "_id" } else { "" }; + let remote_db_column = + resolve_db_column(&r.remote_field, suffix, remote_rel.columns.iter())?; + Some(ArrayRelationship { + name: r.field_name.clone(), + remote_table: r.remote_entity.clone(), + remote_db_column, + }) + }) + .collect(); + + tables.push(Table { + name: entity.name.clone(), + kind: rel.kind, + description: entity.description.clone(), + columns, + primary_key: rel.primary_key.clone(), + object_relationships, + array_relationships, + admin_only: false, + public_aggregations: env.aggregate_entities.contains(&entity.name), + }); + } + + // Effect-cache tables are tracked by the indexer without select + // permissions: visible to admin only. + for (name, rel) in &catalog.relations { + if name.starts_with("envio_effect_") { + tables.push(Table { + name: rel.name.clone(), + kind: rel.kind, + description: None, + columns: rel + .columns + .iter() + .map(|c| Column { + api_name: c.name.clone(), + db_name: c.name.clone(), + pg_type: c.pg_type.clone(), + pg_type_schema: c.pg_type_schema.clone(), + scalar: Scalar::from_pg_type(&c.pg_type, c.is_enum), + is_array: c.is_array, + nullable: c.nullable, + description: None, + }) + .collect(), + primary_key: rel.primary_key.clone(), + object_relationships: vec![], + array_relationships: vec![], + admin_only: true, + public_aggregations: false, + }); + } + } + + if tables.is_empty() { + return Err(anyhow!( + "No tables to serve — has the database been migrated? (run the indexer or `envio local db-migrate setup`)" + )); + } + + if !skipped_entities.is_empty() { + tracing::warn!( + "Skipping entities from schema.graphql with no table in the database: {} — run migrations to expose them", + skipped_entities.join(", ") + ); + } + + tables.sort_by(|a, b| a.name.cmp(&b.name)); + + { + let mut seen: std::collections::HashSet<&str> = std::collections::HashSet::new(); + for t in &tables { + if !seen.insert(&t.name) { + return Err(anyhow!( + "Table name collision: entity \"{}\" in schema.graphql conflicts with an internal indexer table of the same name. Rename the entity.", + t.name + )); + } + } + } + + let model = ServerModel { + tables, + pg_schema: env.pg_schema.clone(), + response_limit: env.response_limit, + }; + + // The admin registry contains every type any role can see; a clean + // admin build guarantees both roles are collision-free. + super::gql::schema_build::check_type_collisions(&model)?; + + Ok(model) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::serve::env_config::{PgSslMode, ServeEnv}; + use crate::serve::pg_catalog::{self, Catalog, Relation, RelationKind}; + use crate::serve::project_schema::ProjectSchema; + + fn test_env() -> ServeEnv { + ServeEnv { + pg_host: "localhost".to_string(), + pg_port: 5432, + pg_user: "postgres".to_string(), + pg_password: "testing".to_string(), + pg_database: "envio-dev".to_string(), + pg_schema: "public".to_string(), + pg_ssl: PgSslMode::Disable, + admin_secret: "testing".to_string(), + response_limit: None, + aggregate_entities: vec![], + query_timeout_ms: None, + pool_wait_timeout_ms: None, + connect_timeout_ms: None, + pool_max_size: 2, + startup_retry_budget_ms: 0, + healthz_timeout_ms: 1_000, + ws_ping_interval_ms: 15_000, + ws_connection_init_timeout_ms: 3_000, + ws_max_connections: 1_000, + ws_max_operations_per_connection: 50, + ws_max_operations: 1_000, + ws_max_concurrent_polls: 1, + ws_poll_interval_ms: 1_000, + ws_max_message_bytes: 1024 * 1024, + } + } + + fn relation(name: &str, columns: &[&str]) -> Relation { + Relation { + name: name.to_string(), + kind: RelationKind::Table, + columns: columns + .iter() + .map(|c| pg_catalog::Column { + name: c.to_string(), + pg_type: "text".to_string(), + pg_type_schema: "pg_catalog".to_string(), + is_array: false, + nullable: false, + is_enum: false, + }) + .collect(), + primary_key: vec!["id".to_string()], + } + } + + fn catalog(relations: Vec) -> Catalog { + Catalog { + relations: relations.into_iter().map(|r| (r.name.clone(), r)).collect(), + } + } + + const SCHEMA: &str = r#" +type User { + id: ID! + "user balance" + tokenBalance: BigInt! + bestGravatar: Gravatar + tokens: [Token!]! @derivedFrom(field: "tokenOwner") +} +type Gravatar { + id: ID! +} +type Token { + id: ID! + tokenOwner: User! +} +"#; + + fn build(schema: &str, catalog: Catalog) -> anyhow::Result { + ServerModel::build(ProjectSchema::parse(schema).unwrap(), catalog, &test_env()) + } + + fn build_err(schema: &str, catalog: Catalog) -> String { + match build(schema, catalog) { + Err(e) => e.to_string(), + Ok(_) => panic!("expected build to fail"), + } + } + + fn user_shape(model: &ServerModel) -> Vec<(String, String, Option)> { + model + .table("User") + .unwrap() + .columns + .iter() + .map(|c| (c.api_name.clone(), c.db_name.clone(), c.description.clone())) + .collect() + } + + #[test] + fn snake_case_format_exposes_original_field_names() { + let model = build( + SCHEMA, + catalog(vec![ + relation("User", &["id", "token_balance", "best_gravatar_id"]), + relation("Gravatar", &["id"]), + relation("Token", &["id", "token_owner_id"]), + ]), + ) + .unwrap(); + assert_eq!( + ( + user_shape(&model), + model + .table("User") + .unwrap() + .object_relationships + .iter() + .map(|r| (r.name.clone(), r.local_db_column.clone())) + .collect::>(), + model + .table("User") + .unwrap() + .array_relationships + .iter() + .map(|r| (r.name.clone(), r.remote_db_column.clone())) + .collect::>(), + ), + ( + vec![ + ("id".to_string(), "id".to_string(), None), + ( + "tokenBalance".to_string(), + "token_balance".to_string(), + Some("user balance".to_string()) + ), + ( + "bestGravatar_id".to_string(), + "best_gravatar_id".to_string(), + None + ), + ], + vec![("bestGravatar".to_string(), "best_gravatar_id".to_string())], + vec![("tokens".to_string(), "token_owner_id".to_string())], + ) + ); + } + + #[test] + fn original_format_keeps_db_names() { + let model = build( + SCHEMA, + catalog(vec![ + relation("User", &["id", "tokenBalance", "bestGravatar_id"]), + relation("Gravatar", &["id"]), + relation("Token", &["id", "tokenOwner_id"]), + ]), + ) + .unwrap(); + assert_eq!( + user_shape(&model), + vec![ + ("id".to_string(), "id".to_string(), None), + ( + "tokenBalance".to_string(), + "tokenBalance".to_string(), + Some("user balance".to_string()) + ), + ( + "bestGravatar_id".to_string(), + "bestGravatar_id".to_string(), + None + ), + ] + ); + } + + #[test] + fn entity_named_like_internal_table_fails() { + let err = build_err( + "type raw_events { id: ID! }", + catalog(vec![relation("raw_events", &["id"])]), + ); + assert!( + err.contains("Table name collision") && err.contains("raw_events"), + "unexpected error: {err}" + ); + } + + #[test] + fn empty_database_explains_how_to_create_tables() { + let err = build_err("type User { id: ID! }", catalog(vec![])); + assert!( + err.contains("No tables to serve"), + "unexpected error: {err}" + ); + assert!( + err.contains("envio local db-migrate setup"), + "unexpected error: {err}" + ); + } + + #[test] + fn entity_colliding_with_generated_type_fails() { + let err = build_err( + "type User { id: ID! }\ntype User_aggregate { id: ID! }", + catalog(vec![ + relation("User", &["id"]), + relation("User_aggregate", &["id"]), + ]), + ); + assert!( + err.contains("type name collision") && err.contains("User_aggregate"), + "unexpected error: {err}" + ); + } + + #[test] + fn entity_colliding_with_builtin_names_fails() { + for name in ["Int", "order_by", "query_root"] { + let err = build_err( + &format!("type {name} {{ id: ID! }}"), + catalog(vec![relation(name, &["id"])]), + ); + assert!( + err.contains("collision") && err.contains(name), + "unexpected error for {name}: {err}" + ); + } + } + + #[test] + fn collision_free_schema_builds() { + let model = build( + SCHEMA, + catalog(vec![ + relation("User", &["id", "tokenBalance", "bestGravatar_id"]), + relation("Gravatar", &["id"]), + relation("Token", &["id", "tokenOwner_id"]), + relation("raw_events", &["id"]), + ]), + ) + .unwrap(); + assert_eq!( + model + .tables + .iter() + .map(|t| t.name.as_str()) + .collect::>(), + vec!["Gravatar", "Token", "User", "raw_events"] + ); + } +} diff --git a/packages/cli/src/serve/pg_catalog.rs b/packages/cli/src/serve/pg_catalog.rs new file mode 100644 index 0000000000..446fe396e2 --- /dev/null +++ b/packages/cli/src/serve/pg_catalog.rs @@ -0,0 +1,134 @@ +//! Live Postgres catalog introspection — the source of truth for column +//! shapes, exactly like Hasura's own source introspection. + +use anyhow::Context; +use std::collections::HashMap; + +pub struct Catalog { + /// Tables and views in the target schema, keyed by relation name. + pub relations: HashMap, +} + +pub struct Relation { + pub name: String, + pub kind: RelationKind, + pub columns: Vec, + /// Primary key column names, in key order. Empty for views. + pub primary_key: Vec, +} + +#[derive(PartialEq, Eq, Clone, Copy)] +pub enum RelationKind { + Table, + View, +} + +#[derive(Clone)] +pub struct Column { + pub name: String, + /// Base type name from pg_type (e.g. "text", "int4", "numeric", + /// "timestamptz", or an enum type name like "accounttype"). + pub pg_type: String, + /// Namespace owning the base/element type (`pg_catalog` for builtins, + /// the project schema for enums and other custom types). + pub pg_type_schema: String, + pub is_array: bool, + pub nullable: bool, + pub is_enum: bool, +} + +pub async fn introspect( + pool: &deadpool_postgres::Pool, + pg_schema: &str, +) -> anyhow::Result { + let client = pool.get().await.context("Failed acquiring PG connection")?; + + let column_rows = client + .query( + r#" + SELECT + c.relname::text AS table_name, + c.relkind::text AS relkind, + a.attname::text AS column_name, + CASE WHEN t.typtype = 'd' THEN bt_base.typname ELSE base_t.typname END::text AS pg_type, + CASE + WHEN t.typtype = 'd' THEN bt_ns.nspname + WHEN t.typcategory = 'A' THEN elem_ns.nspname + ELSE type_ns.nspname + END::text AS pg_type_schema, + (t.typcategory = 'A')::bool AS is_array, + NOT (a.attnotnull)::bool AS nullable, + (CASE WHEN t.typcategory = 'A' THEN elem_t.typtype ELSE t.typtype END = 'e')::bool AS is_enum, + a.attnum + FROM pg_class c + JOIN pg_namespace n ON n.oid = c.relnamespace + JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum > 0 AND NOT a.attisdropped + JOIN pg_type t ON t.oid = a.atttypid + LEFT JOIN pg_type elem_t ON elem_t.oid = t.typelem + LEFT JOIN pg_type bt_base ON t.typtype = 'd' AND bt_base.oid = t.typbasetype + LEFT JOIN pg_namespace type_ns ON type_ns.oid = t.typnamespace + LEFT JOIN pg_namespace elem_ns ON elem_ns.oid = elem_t.typnamespace + LEFT JOIN pg_namespace bt_ns ON bt_ns.oid = bt_base.typnamespace + JOIN LATERAL ( + SELECT CASE WHEN t.typcategory = 'A' THEN elem_t.typname ELSE t.typname END AS typname + ) base_t ON true + WHERE n.nspname = $1 AND c.relkind IN ('r', 'v', 'm') + ORDER BY c.relname, a.attnum + "#, + &[&pg_schema], + ) + .await + .context("Failed querying pg_catalog for columns")?; + + let pk_rows = client + .query( + r#" + SELECT c.relname::text AS table_name, a.attname::text AS column_name, k.ordinality + FROM pg_index i + JOIN pg_class c ON c.oid = i.indrelid + JOIN pg_namespace n ON n.oid = c.relnamespace + JOIN LATERAL unnest(i.indkey) WITH ORDINALITY AS k(attnum, ordinality) ON true + JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = k.attnum + WHERE n.nspname = $1 AND i.indisprimary + ORDER BY c.relname, k.ordinality + "#, + &[&pg_schema], + ) + .await + .context("Failed querying pg_catalog for primary keys")?; + + let mut relations: HashMap = HashMap::new(); + for row in column_rows { + let table_name: String = row.get("table_name"); + let relkind: String = row.get("relkind"); + let relation = relations + .entry(table_name.clone()) + .or_insert_with(|| Relation { + name: table_name, + kind: if relkind == "r" { + RelationKind::Table + } else { + RelationKind::View + }, + columns: Vec::new(), + primary_key: Vec::new(), + }); + relation.columns.push(Column { + name: row.get("column_name"), + pg_type: row.get("pg_type"), + pg_type_schema: row.get("pg_type_schema"), + is_array: row.get("is_array"), + nullable: row.get("nullable"), + is_enum: row.get("is_enum"), + }); + } + + for row in pk_rows { + let table_name: String = row.get("table_name"); + if let Some(rel) = relations.get_mut(&table_name) { + rel.primary_key.push(row.get("column_name")); + } + } + + Ok(Catalog { relations }) +} diff --git a/packages/cli/src/serve/project_schema.rs b/packages/cli/src/serve/project_schema.rs new file mode 100644 index 0000000000..bd37a86524 --- /dev/null +++ b/packages/cli/src/serve/project_schema.rs @@ -0,0 +1,314 @@ +//! Minimal, version-tolerant project file reading for `envio serve`. +//! +//! `config.yaml` is read with a hand-rolled reader that only looks at the +//! top-level `schema` field (the path to schema.graphql, defaulting to +//! "schema.graphql" next to the config file). Unlike the strict +//! `HumanConfig` deserializers, this accepts configs written for any envio +//! version >= 2.21.5 — old or new fields never cause a failure. +//! +//! `schema.graphql` is likewise parsed leniently: entity names, every +//! db-backed field name (needed to map GraphQL field names to columns when +//! the project uses `column_name_format: snake_case`), entity-reference +//! fields (object relationships) and `@derivedFrom` fields (array +//! relationships) are extracted; column shapes come from live Postgres +//! introspection. + +use crate::project_paths::ParsedProjectPaths; +use anyhow::{anyhow, Context}; +use graphql_parser::schema as gql; + +pub struct ProjectSchema { + pub entities: Vec, +} + +pub struct EntityDef { + pub name: String, + pub description: Option, + /// field name -> referenced entity (fields typed as another entity) + pub object_relationships: Vec, + /// @derivedFrom fields + pub array_relationships: Vec, + /// Every field backed by a db column (scalars and enums — everything + /// that is neither an entity reference nor @derivedFrom), in schema + /// order. + pub scalar_fields: Vec, +} + +pub struct ScalarField { + pub name: String, + pub description: Option, +} + +pub struct ObjectRel { + pub field_name: String, + pub remote_entity: String, +} + +pub struct ArrayRel { + pub field_name: String, + pub remote_entity: String, + /// The field on the remote entity named by @derivedFrom(field: ...) + pub remote_field: String, +} + +impl ProjectSchema { + pub fn load( + project_paths: &ParsedProjectPaths, + _env: &super::env_config::ServeEnv, + ) -> anyhow::Result { + let config_text = std::fs::read_to_string(&project_paths.config).with_context(|| { + format!( + "Failed reading config file at {}", + project_paths.config.display() + ) + })?; + let schema_rel_path = read_schema_field(&config_text)?; + + let config_dir = project_paths + .config + .parent() + .ok_or_else(|| anyhow!("Config path has no parent directory"))?; + let schema_path = config_dir.join(&schema_rel_path); + let schema_text = std::fs::read_to_string(&schema_path).with_context(|| { + format!("Failed reading GraphQL schema at {}", schema_path.display()) + })?; + + Self::parse(&schema_text) + } + + pub fn parse(schema_text: &str) -> anyhow::Result { + let doc: gql::Document = + graphql_parser::parse_schema(schema_text).context("Failed parsing schema.graphql")?; + + let entity_names: Vec = doc + .definitions + .iter() + .filter_map(|d| match d { + gql::Definition::TypeDefinition(gql::TypeDefinition::Object(o)) => { + Some(o.name.clone()) + } + _ => None, + }) + .collect(); + + let mut entities = Vec::new(); + for def in &doc.definitions { + let gql::Definition::TypeDefinition(gql::TypeDefinition::Object(obj)) = def else { + continue; + }; + let mut object_relationships = Vec::new(); + let mut array_relationships = Vec::new(); + let mut scalar_fields = Vec::new(); + + for field in &obj.fields { + let base = base_type_name(&field.field_type); + let derived_from_field = field.directives.iter().find_map(|d| { + if d.name != "derivedFrom" { + return None; + } + d.arguments.iter().find_map(|(name, value)| { + if name == "field" { + match value { + gql::Value::String(s) => Some(s.clone()), + _ => None, + } + } else { + None + } + }) + }); + + // Hasura.res's makeColumnConfigs only sends a `comment` for + // plain db-backed fields, never for relationship fields + // (Table.DerivedFrom is skipped outright, and entity-reference + // fields never produce a Table.Field entry) — so relationship + // fields must not feed scalar_fields here. + if let Some(remote_field) = derived_from_field { + if entity_names.contains(&base) { + array_relationships.push(ArrayRel { + field_name: field.name.clone(), + remote_entity: base, + remote_field, + }); + continue; + } + } else if entity_names.contains(&base) && !is_list_type(&field.field_type) { + object_relationships.push(ObjectRel { + field_name: field.name.clone(), + remote_entity: base, + }); + continue; + } + scalar_fields.push(ScalarField { + name: field.name.clone(), + description: field.description.clone(), + }); + } + + entities.push(EntityDef { + name: obj.name.clone(), + description: obj.description.clone(), + object_relationships, + array_relationships, + scalar_fields, + }); + } + + Ok(ProjectSchema { entities }) + } +} + +fn base_type_name(t: &gql::Type) -> String { + match t { + gql::Type::NamedType(n) => n.clone(), + gql::Type::ListType(inner) | gql::Type::NonNullType(inner) => base_type_name(inner), + } +} + +fn is_list_type(t: &gql::Type) -> bool { + match t { + gql::Type::NamedType(_) => false, + gql::Type::ListType(_) => true, + gql::Type::NonNullType(inner) => is_list_type(inner), + } +} + +/// Reads only the top-level `schema` scalar from config.yaml without +/// deserializing into any versioned struct. +fn read_schema_field(config_text: &str) -> anyhow::Result { + let value: serde_yaml::Value = + serde_yaml::from_str(config_text).context("Failed parsing config.yaml as YAML")?; + match value + .as_mapping() + .and_then(|m| m.get(serde_yaml::Value::String("schema".to_string()))) + { + None => Ok("schema.graphql".to_string()), + Some(v) => v.as_str().map(|s| s.to_string()).ok_or_else(|| { + let shown = serde_yaml::to_string(v) + .map(|s| s.trim_end().to_string()) + .unwrap_or_else(|_| format!("{v:?}")); + anyhow!( + "Invalid `schema` value in config.yaml: expected a string path to the GraphQL schema, got: {shown}" + ) + }), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn schema_field_default_and_custom() { + assert_eq!( + read_schema_field("name: test\ncontracts: []\n").unwrap(), + "schema.graphql" + ); + assert_eq!( + read_schema_field("name: x\nschema: ./custom/path.graphql\n").unwrap(), + "./custom/path.graphql" + ); + } + + #[test] + fn tolerates_unknown_and_legacy_fields() { + // 2.21.5-era config with fields the current HumanConfig rejects or + // never knew about must still parse. + let legacy = r#" +name: legacy +description: old +schema: ./schema.graphql +unordered_multichain_mode: true +event_decoder: hypersync-client +networks: + - id: 1 + start_block: 0 + contracts: [] +some_future_field: + nested: [1, 2] +"#; + assert_eq!(read_schema_field(legacy).unwrap(), "./schema.graphql"); + } + + #[test] + fn reads_real_2_21_5_config_fixtures() { + // Authentic v2.21.5 config shape (verbatim from the v2.21.5 tag, + // trimmed): networks/rpc_config keys, no schema field -> default. + let legacy = std::fs::read_to_string(concat!( + env!("CARGO_MANIFEST_DIR"), + "/test/configs/serve-legacy-2.21.5.yaml" + )) + .unwrap(); + assert_eq!(read_schema_field(&legacy).unwrap(), "schema.graphql"); + + let custom = std::fs::read_to_string(concat!( + env!("CARGO_MANIFEST_DIR"), + "/test/configs/serve-legacy-2.21.5-custom-schema.yaml" + )) + .unwrap(); + assert_eq!( + read_schema_field(&custom).unwrap(), + "./schemas/gravatar-schema.graphql" + ); + } + + #[test] + fn non_string_schema_value_is_an_error() { + let err = read_schema_field("schema:\n nested: true\n") + .unwrap_err() + .to_string(); + assert!( + err.contains("Invalid `schema` value") && err.contains("nested"), + "unexpected error: {err}" + ); + let err = read_schema_field("schema: 42\n").unwrap_err().to_string(); + assert!( + err.contains("Invalid `schema` value") && err.contains("42"), + "unexpected error: {err}" + ); + } + + #[test] + fn parses_relationships() { + let schema = r#" +type User { + id: ID! + "user balance" + tokenBalance: BigInt! + gravatar: Gravatar + tokens: [Token!]! @derivedFrom(field: "owner") +} +type Gravatar { + id: ID! + owner: User! +} +type Token { + id: ID! + owner: User! +} +"#; + let parsed = ProjectSchema::parse(schema).unwrap(); + let user = parsed.entities.iter().find(|e| e.name == "User").unwrap(); + assert_eq!( + ( + user.object_relationships + .iter() + .map(|r| r.field_name.as_str()) + .collect::>(), + user.array_relationships + .iter() + .map(|r| (r.field_name.as_str(), r.remote_field.as_str())) + .collect::>(), + user.scalar_fields + .iter() + .map(|f| (f.name.as_str(), f.description.as_deref())) + .collect::>(), + ), + ( + vec!["gravatar"], + vec![("tokens", "owner")], + vec![("id", None), ("tokenBalance", Some("user balance"))] + ) + ); + } +} diff --git a/packages/cli/src/serve/robustness_tests.rs b/packages/cli/src/serve/robustness_tests.rs new file mode 100644 index 0000000000..9a6d1ed5b2 --- /dev/null +++ b/packages/cli/src/serve/robustness_tests.rs @@ -0,0 +1,1476 @@ +//! Failure-mode regression tests: each pins a production behavior against +//! a throwaway Postgres container (skipped when docker isn't available, +//! like env_config's TLS test). +//! +//! Pinned behaviors: +//! - a Postgres outage produces fast, clean GraphQL errors and a failing +//! /healthz, and the server self-heals without a restart; +//! - recreating a table mid-flight does not poison the prepared-statement +//! cache (guaranteed by the `(...)::text AS "root"` output shape — every +//! statement's outer row type is a single text column, so schema changes +//! never change a cached plan's result type); +//! - a frozen (SIGSTOP'd) Postgres cannot hang requests beyond the +//! client-side query timeout; +//! - the shutdown signal actually stops the server, and active WebSocket +//! subscriptions get a `complete` frame plus a 1001 close instead of a +//! dropped socket; +//! - a null `arguments` on an aggregate bool_exp predicate is a validation +//! error for every op except `count` (whose `arguments` list is genuinely +//! nullable), instead of reaching SQL generation and producing invalid +//! syntax like `bool_and(*)`; +//! - a null `distinct` on an aggregate bool_exp predicate, on an aggregate +//! selection's `count`, and a null `path` on a json/jsonb field are each +//! validation errors, not a silent false/count(*)/whole-value fallback — +//! confirmed against a live Hasura 2.43.0 instance for each case; +//! - a WebSocket client that goes silent (no reads or writes, connection +//! otherwise alive) is closed within 30s instead of leaking a subscription +//! poll loop forever; +//! - `envio serve` started before Postgres is reachable retries within its +//! startup budget and becomes healthy once Postgres comes up. +//! - startup failures name the unreachable endpoint, rejected credentials, +//! or missing database and point to the exact environment variables to fix. + +use super::env_config::{PgSslMode, ServeEnv}; +use super::model::ServerModel; +use super::project_schema::ProjectSchema; +use super::test_support::{free_port, skip_without_docker, TestPg}; +use super::{http, pg_catalog, ServeState}; +use crate::project_paths::ParsedProjectPaths; +use futures_util::{SinkExt, StreamExt}; +use std::sync::Arc; +use std::time::{Duration, Instant}; + +fn test_env(pg_port: u16) -> ServeEnv { + ServeEnv { + pg_host: "localhost".to_string(), + pg_port, + pg_user: "postgres".to_string(), + pg_password: "testing".to_string(), + pg_database: "envio-dev".to_string(), + pg_schema: "public".to_string(), + pg_ssl: PgSslMode::Disable, + admin_secret: "testing".to_string(), + response_limit: None, + aggregate_entities: vec![], + query_timeout_ms: Some(120_000), + pool_wait_timeout_ms: Some(15_000), + connect_timeout_ms: Some(5_000), + pool_max_size: 8, + startup_retry_budget_ms: 60_000, + healthz_timeout_ms: 2_000, + ws_ping_interval_ms: 15_000, + ws_connection_init_timeout_ms: 3_000, + ws_max_connections: 1_000, + ws_max_operations_per_connection: 50, + ws_max_operations: 1_000, + ws_max_concurrent_polls: 6, + ws_poll_interval_ms: 1_000, + ws_max_message_bytes: 1024 * 1024, + } +} + +struct TestServer { + port: u16, + pool: deadpool_postgres::Pool, + shutdown: Option>, + handle: tokio::task::JoinHandle>, +} + +/// Applies the differential fixture schema/seed (plus optional test-local +/// extra DDL) to the pool's Postgres, retrying the connection while the +/// container is still coming up. Panics if it can't get a connection at all +/// within the retry budget. +async fn apply_fixture(pool: &deadpool_postgres::Pool, extra_sql: Option<&str>) { + let fixture_dir = concat!( + env!("CARGO_MANIFEST_DIR"), + "/../e2e-tests/fixtures/differential" + ); + for _ in 0..20 { + let Ok(client) = pool.get().await else { + tokio::time::sleep(Duration::from_millis(500)).await; + continue; + }; + for file in ["schema.sql", "seed.sql"] { + let sql = std::fs::read_to_string(format!("{fixture_dir}/{file}")).unwrap(); + client.batch_execute(&sql).await.expect("fixture applies"); + } + if let Some(sql) = extra_sql { + client + .batch_execute(sql) + .await + .expect("extra fixture SQL applies"); + } + return; + } + panic!("could not reach the test Postgres to apply fixtures"); +} + +/// Applies the differential fixture to the container and boots the server +/// in-process on an ephemeral port, exactly as `serve::run` wires it minus +/// the OS signal handler. +async fn boot( + env: ServeEnv, + query_timeout: Option, + extra_sql: Option<&str>, +) -> TestServer { + let pool = env.make_pg_pool().expect("pool"); + apply_fixture(&pool, extra_sql).await; + + let project_root = concat!(env!("CARGO_MANIFEST_DIR"), "/../../scenarios/test_codegen"); + let paths = ParsedProjectPaths::new(project_root, "config.yaml").unwrap(); + let project_schema = ProjectSchema::load(&paths, &env).unwrap(); + let catalog = pg_catalog::introspect(&pool, &env.pg_schema).await.unwrap(); + let model = ServerModel::build(project_schema, catalog, &env).unwrap(); + + let state = Arc::new(ServeState { + model, + pool: pool.clone(), + admin_secret: env.admin_secret.clone(), + query_timeout, + healthz_timeout: Duration::from_millis(env.healthz_timeout_ms), + ws_ping_interval: Duration::from_millis(env.ws_ping_interval_ms), + ws_connection_init_timeout: Duration::from_millis(env.ws_connection_init_timeout_ms), + ws_max_connections: env.ws_max_connections, + ws_max_operations_per_connection: env.ws_max_operations_per_connection, + ws_max_operations: env.ws_max_operations, + ws_max_concurrent_polls: env.ws_max_concurrent_polls, + ws_poll_interval: Duration::from_millis(env.ws_poll_interval_ms), + ws_max_message_bytes: env.ws_max_message_bytes, + }); + + let port = { + let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + listener.local_addr().unwrap().port() + }; + let (tx, rx) = tokio::sync::oneshot::channel::<()>(); + let handle = tokio::spawn(http::serve(state, "127.0.0.1", port, async move { + let _ = rx.await; + })); + + let client = reqwest::Client::new(); + for _ in 0..40 { + if let Ok(res) = client + .get(format!("http://127.0.0.1:{port}/healthz")) + .timeout(Duration::from_secs(3)) + .send() + .await + { + if res.status().as_u16() == 200 { + return TestServer { + port, + pool, + shutdown: Some(tx), + handle, + }; + } + } + tokio::time::sleep(Duration::from_millis(250)).await; + } + panic!("in-process envio serve did not become healthy"); +} + +impl TestServer { + async fn graphql(&self, query: &str, timeout: Duration) -> (u16, serde_json::Value) { + let res = reqwest::Client::new() + .post(format!("http://127.0.0.1:{}/v1/graphql", self.port)) + .header("content-type", "application/json") + .body(serde_json::json!({ "query": query }).to_string()) + .timeout(timeout) + .send() + .await + .expect("request should get an HTTP response"); + let status = res.status().as_u16(); + let body: serde_json::Value = res.json().await.expect("JSON body"); + (status, body) + } + + async fn healthz(&self) -> u16 { + reqwest::Client::new() + .get(format!("http://127.0.0.1:{}/healthz", self.port)) + .timeout(Duration::from_secs(5)) + .send() + .await + .map(|r| r.status().as_u16()) + .unwrap_or(0) + } +} + +fn db_error_body(message: &str, code: &str) -> serde_json::Value { + serde_json::json!({ + "errors": [{ + "message": message, + "extensions": { "path": "$", "code": code } + }] + }) +} + +const SIMPLE_QUERY: &str = "{ SimpleEntity(order_by: {id: asc}, limit: 1) { id } }"; + +#[tokio::test(flavor = "multi_thread")] +async fn postgres_outage_errors_cleanly_and_recovers_without_restart() { + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let server = boot(test_env(pg.port), Some(Duration::from_secs(20)), None).await; + + let (status, body) = server.graphql(SIMPLE_QUERY, Duration::from_secs(10)).await; + assert_eq!( + ( + status, + body["data"]["SimpleEntity"].is_array(), + server.healthz().await + ), + (200, true, 200) + ); + + pg.docker("kill"); + + // Requests during the outage: fast, clean GraphQL error — not a hang, + // not a connection reset. + let started = Instant::now(); + let (status, body) = server.graphql(SIMPLE_QUERY, Duration::from_secs(30)).await; + assert_eq!( + ( + status, + body, + started.elapsed() < Duration::from_secs(25), + server.healthz().await + ), + ( + 200, + db_error_body("database query error", "postgres-error"), + true, + 500 + ) + ); + + pg.docker("start"); + + // Self-heals with no server restart: the pool discards dead + // connections and dials fresh ones. + let deadline = Instant::now() + Duration::from_secs(30); + loop { + let (status, body) = server.graphql(SIMPLE_QUERY, Duration::from_secs(10)).await; + if status == 200 && body["data"]["SimpleEntity"].is_array() { + break; + } + assert!( + Instant::now() < deadline, + "server did not recover after Postgres came back: {status} {body}" + ); + tokio::time::sleep(Duration::from_millis(500)).await; + } + assert_eq!(server.healthz().await, 200); +} + +#[tokio::test(flavor = "multi_thread")] +async fn table_recreate_does_not_poison_statement_cache() { + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let server = boot(test_env(pg.port), Some(Duration::from_secs(20)), None).await; + + let query = "{ SimpleEntity(order_by: {id: asc}) { id value } }"; + for _ in 0..3 { + let (status, _) = server.graphql(query, Duration::from_secs(10)).await; + assert_eq!(status, 200); + } + + // Full re-migration while statements are cached: new relation OID, + // same shape. This is what an indexer redeploy does under a running + // serve process. + let client = server.pool.get().await.unwrap(); + client + .batch_execute( + r#" + DROP TABLE public."SimpleEntity" CASCADE; + CREATE TABLE public."SimpleEntity" (id text NOT NULL, value text NOT NULL); + ALTER TABLE ONLY public."SimpleEntity" ADD CONSTRAINT "SimpleEntity_pkey" PRIMARY KEY (id); + INSERT INTO public."SimpleEntity" (id, value) VALUES ('after-recreate', 'v'); + "#, + ) + .await + .unwrap(); + drop(client); + + // Every pooled connection (not just one) must keep working; hit the + // endpoint several times to cycle through them. + for _ in 0..5 { + let (status, body) = server.graphql(query, Duration::from_secs(10)).await; + assert_eq!( + (status, body), + ( + 200, + serde_json::json!({"data": {"SimpleEntity": [{"id": "after-recreate", "value": "v"}]}}) + ) + ); + } +} + +#[tokio::test(flavor = "multi_thread")] +async fn frozen_postgres_is_bounded_by_the_client_query_timeout() { + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + // Short client-side timeout; the server-side statement_timeout can't + // fire because Postgres is frozen, so this is the only bound. + let server = boot(test_env(pg.port), Some(Duration::from_secs(3)), None).await; + + let (status, _) = server.graphql(SIMPLE_QUERY, Duration::from_secs(10)).await; + assert_eq!(status, 200); + + pg.docker("pause"); + let started = Instant::now(); + let (status, body) = server.graphql(SIMPLE_QUERY, Duration::from_secs(30)).await; + let elapsed = started.elapsed(); + pg.docker("unpause"); + + assert_eq!( + ( + status, + body, + elapsed > Duration::from_secs(2) && elapsed < Duration::from_secs(15) + ), + ( + 200, + db_error_body("database query timeout", "unexpected"), + true + ) + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn shutdown_signal_stops_the_server() { + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut server = boot(test_env(pg.port), Some(Duration::from_secs(20)), None).await; + + let (status, _) = server.graphql(SIMPLE_QUERY, Duration::from_secs(10)).await; + assert_eq!(status, 200); + + server.shutdown.take().unwrap().send(()).unwrap(); + let serve_result = tokio::time::timeout(Duration::from_secs(15), &mut server.handle) + .await + .expect("server should stop within the drain timeout") + .expect("serve task should not panic"); + let new_request = reqwest::Client::new() + .get(format!("http://127.0.0.1:{}/healthz", server.port)) + .timeout(Duration::from_secs(2)) + .send() + .await; + assert_eq!( + (serve_result.is_ok(), new_request.is_err()), + (true, true), + "server should exit cleanly and stop accepting connections" + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn aggregate_bool_exp_null_arguments_errors_cleanly() { + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + // Exposes Token_aggregate_bool_exp (incl. bool_and/bool_or, once Token + // has a boolean column) on NftCollection_bool_exp.tokens_aggregate for + // the public role, mirroring aggregations_enabled's `table.public_aggregations` + // check in gql/schema_build.rs. + env.aggregate_entities = vec!["Token".to_string()]; + let server = boot( + env, + Some(Duration::from_secs(20)), + Some(r#"ALTER TABLE public."Token" ADD COLUMN is_special boolean NOT NULL DEFAULT false;"#), + ) + .await; + + // Omitting `arguments` entirely means count(*): confirmed live against + // Hasura 2.43.0 on this exact fixture (this data shape and row set is + // its real recorded response, not a guess). + let (status, body) = server + .graphql( + "{ NftCollection(where: {tokens_aggregate: {count: {predicate: {_gte: 0}}}}) { id } }", + Duration::from_secs(10), + ) + .await; + assert_eq!( + (status, body), + ( + 200, + serde_json::json!({"data": {"NftCollection": [ + {"id": "coll-1"}, {"id": "coll-2"}, {"id": "coll-3"} + ]}}) + ) + ); + + // An explicit `arguments: null` is a validation error even for count, + // whose `arguments` is a nullable *list* type — Hasura rejects the null + // literal itself rather than treating it as an omitted key. Wording and + // path confirmed live against Hasura 2.43.0 on this exact query. + let (status, body) = server + .graphql( + "{ NftCollection(where: {tokens_aggregate: {count: {arguments: null, predicate: {_gte: 0}}}}) { id } }", + Duration::from_secs(10), + ) + .await; + assert_eq!( + (status, body), + ( + 200, + serde_json::json!({"errors": [{ + "message": "expected a list, but found null", + "extensions": { + "path": "$.selectionSet.NftCollection.args.where.tokens_aggregate.count.arguments", + "code": "validation-failed" + } + }]}) + ) + ); + + // bool_and/bool_or's `arguments` is a single non-null column enum: a + // null literal must be rejected as a validation error up front, not + // passed through to SQL generation as `bool_and(*)` (invalid syntax — + // only count(*) accepts the bare-`*` form). Wording and path confirmed + // live against Hasura 2.43.0 on this exact query. + let (status, body) = server + .graphql( + "{ NftCollection(where: {tokens_aggregate: {bool_and: {arguments: null, predicate: {_eq: true}}}}) { id } }", + Duration::from_secs(10), + ) + .await; + assert_eq!( + (status, body), + ( + 200, + serde_json::json!({"errors": [{ + "message": "expected an enum value for type 'Token_select_column_Token_aggregate_bool_exp_bool_and_arguments_columns', but found null", + "extensions": { + "path": "$.selectionSet.NftCollection.args.where.tokens_aggregate.bool_and.arguments", + "code": "validation-failed" + } + }]}) + ) + ); + + // `distinct` is a plain Boolean field: a null literal must be rejected, + // not silently treated as `false`. Wording and path confirmed live + // against Hasura 2.43.0 on this exact query. + let (status, body) = server + .graphql( + "{ NftCollection(where: {tokens_aggregate: {count: {distinct: null, predicate: {_gte: 0}}}}) { id } }", + Duration::from_secs(10), + ) + .await; + assert_eq!( + (status, body), + ( + 200, + serde_json::json!({"errors": [{ + "message": "expected a boolean for type 'Boolean', but found null", + "extensions": { + "path": "$.selectionSet.NftCollection.args.where.tokens_aggregate.count.distinct", + "code": "validation-failed" + } + }]}) + ) + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn http_transport_surface_edge_cases() { + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let server = boot(test_env(pg.port), Some(Duration::from_secs(20)), None).await; + let base = format!("http://127.0.0.1:{}", server.port); + let client = reqwest::Client::new(); + + // GET /v1/graphql without WebSocket upgrade headers: axum's upgrade + // extractor rejects it (serve-defined behavior, pinned here — Hasura + // serves GraphiQL on plain GET instead). + let res = client + .get(format!("{base}/v1/graphql")) + .timeout(Duration::from_secs(5)) + .send() + .await + .unwrap(); + let get_status = res.status().as_u16(); + let get_body = res.text().await.unwrap(); + + let unknown_path_status = client + .get(format!("{base}/definitely/not/a/route")) + .timeout(Duration::from_secs(5)) + .send() + .await + .unwrap() + .status() + .as_u16(); + + // >2MB body trips the explicit request-body limit before GraphQL parsing + // (serve-defined behavior, pinned independently of axum defaults). + let oversized = format!( + "{{\"query\": \"{{ SimpleEntity {{ id }} }}\", \"pad\": \"{}\"}}", + "a".repeat(3 * 1024 * 1024) + ); + let res = client + .post(format!("{base}/v1/graphql")) + .header("content-type", "application/json") + .body(oversized) + .timeout(Duration::from_secs(10)) + .send() + .await + .unwrap(); + let oversized_status = res.status().as_u16(); + let oversized_body = res.text().await.unwrap(); + + assert_eq!( + ( + get_status, + get_body, + unknown_path_status, + oversized_status, + oversized_body + ), + ( + 400, + "Connection header did not include 'upgrade'".to_string(), + 404, + 413, + "Failed to buffer the request body: length limit exceeded".to_string() + ) + ); +} + +const SUBSCRIBE_QUERY: &str = "subscription { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }"; + +#[tokio::test(flavor = "multi_thread")] +async fn websocket_connection_init_deadline_is_not_extended_by_ping_traffic() { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::tungstenite::http::HeaderValue; + use tokio_tungstenite::tungstenite::Message as TMessage; + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + env.ws_connection_init_timeout_ms = 250; + let server = boot(env, Some(Duration::from_secs(20)), None).await; + + let mut request = format!("ws://127.0.0.1:{}/v1/graphql", server.port) + .into_client_request() + .unwrap(); + request.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_static("graphql-transport-ws"), + ); + let (mut ws, _) = tokio_tungstenite::connect_async(request) + .await + .expect("websocket handshake"); + + let close_code = tokio::time::timeout(Duration::from_secs(2), async { + let mut ping = tokio::time::interval(Duration::from_millis(40)); + loop { + tokio::select! { + _ = ping.tick() => { + ws.send(TMessage::Text( + serde_json::json!({"type": "ping"}).to_string().into() + )).await.expect("ping send"); + } + message = ws.next() => match message { + Some(Ok(TMessage::Close(frame))) => { + return frame.map(|f| u16::from(f.code)); + } + Some(Ok(_)) => {} + Some(Err(_)) | None => return None, + } + } + } + }) + .await + .expect("uninitialized websocket should be closed"); + + assert_eq!(close_code, Some(4408)); +} + +#[tokio::test(flavor = "multi_thread")] +async fn websocket_operation_limit_rejects_before_starting_more_work() { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::tungstenite::http::HeaderValue; + use tokio_tungstenite::tungstenite::Message as TMessage; + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + env.ws_max_operations_per_connection = 1; + let server = boot(env, Some(Duration::from_secs(20)), None).await; + + let mut request = format!("ws://127.0.0.1:{}/v1/graphql", server.port) + .into_client_request() + .unwrap(); + request.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_static("graphql-transport-ws"), + ); + let (mut ws, _) = tokio_tungstenite::connect_async(request) + .await + .expect("websocket handshake"); + + ws.send(TMessage::Text( + serde_json::json!({"type": "connection_init"}) + .to_string() + .into(), + )) + .await + .unwrap(); + let _ack = ws.next().await.expect("connection_ack frame").unwrap(); + + for id in ["one", "two"] { + ws.send(TMessage::Text( + serde_json::json!({ + "id": id, + "type": "subscribe", + "payload": { "query": SUBSCRIBE_QUERY } + }) + .to_string() + .into(), + )) + .await + .unwrap(); + if id == "one" { + let first = tokio::time::timeout(Duration::from_secs(5), ws.next()) + .await + .expect("first operation should start") + .unwrap() + .unwrap(); + assert!(matches!(first, TMessage::Text(_))); + } + } + + let close_code = tokio::time::timeout(Duration::from_secs(2), async { + loop { + match ws.next().await { + Some(Ok(TMessage::Close(frame))) => { + return frame.map(|f| u16::from(f.code)); + } + Some(Ok(_)) => {} + Some(Err(_)) | None => return None, + } + } + }) + .await + .expect("operation overflow should close the socket"); + assert_eq!(close_code, Some(1008)); +} + +#[tokio::test(flavor = "multi_thread")] +async fn websocket_global_operation_limit_applies_across_connections() { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::tungstenite::http::HeaderValue; + use tokio_tungstenite::tungstenite::Message as TMessage; + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + env.ws_max_operations_per_connection = 1; + env.ws_max_operations = 1; + let server = boot(env, Some(Duration::from_secs(20)), None).await; + + let port = server.port; + let connect = move || async move { + let mut request = format!("ws://127.0.0.1:{port}/v1/graphql") + .into_client_request() + .unwrap(); + request.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_static("graphql-transport-ws"), + ); + tokio_tungstenite::connect_async(request) + .await + .expect("websocket handshake") + .0 + }; + let mut first = connect().await; + let mut second = connect().await; + for ws in [&mut first, &mut second] { + ws.send(TMessage::Text( + serde_json::json!({"type": "connection_init"}) + .to_string() + .into(), + )) + .await + .unwrap(); + let _ack = ws.next().await.expect("connection_ack frame").unwrap(); + } + + first + .send(TMessage::Text( + serde_json::json!({ + "id": "one", + "type": "subscribe", + "payload": { "query": SUBSCRIBE_QUERY } + }) + .to_string() + .into(), + )) + .await + .unwrap(); + let _first_result = tokio::time::timeout(Duration::from_secs(5), first.next()) + .await + .expect("first global operation should start") + .unwrap() + .unwrap(); + + second + .send(TMessage::Text( + serde_json::json!({ + "id": "two", + "type": "subscribe", + "payload": { "query": SUBSCRIBE_QUERY } + }) + .to_string() + .into(), + )) + .await + .unwrap(); + let close_code = tokio::time::timeout(Duration::from_secs(2), async { + loop { + match second.next().await { + Some(Ok(TMessage::Close(frame))) => { + return frame.map(|f| u16::from(f.code)); + } + Some(Ok(_)) => {} + Some(Err(_)) | None => return None, + } + } + }) + .await + .expect("global operation overflow should close the second socket"); + assert_eq!(close_code, Some(1013)); +} + +#[tokio::test(flavor = "multi_thread")] +async fn identical_live_queries_share_one_postgres_poll_loop() { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::tungstenite::http::HeaderValue; + use tokio_tungstenite::tungstenite::Message as TMessage; + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + env.ws_poll_interval_ms = 200; + // The view preserves SimpleEntity's API but advances a sequence whenever + // its id is read. With `limit: 1`, that gives a precise database-side + // count of live-query polls without relying on timing-sensitive server + // instrumentation. + let server = boot( + env, + Some(Duration::from_secs(20)), + Some( + r#" + ALTER TABLE public."SimpleEntity" RENAME TO "SimpleEntity_backing"; + CREATE SEQUENCE public.live_query_poll_count; + CREATE VIEW public."SimpleEntity" AS + SELECT + id || CASE WHEN nextval('public.live_query_poll_count') > 0 THEN '' ELSE NULL END AS id, + value + FROM public."SimpleEntity_backing"; + "#, + ), + ) + .await; + + let mut request = format!("ws://127.0.0.1:{}/v1/graphql", server.port) + .into_client_request() + .unwrap(); + request.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_static("graphql-transport-ws"), + ); + let (mut ws, _) = tokio_tungstenite::connect_async(request) + .await + .expect("websocket handshake"); + ws.send(TMessage::Text( + serde_json::json!({"type": "connection_init"}) + .to_string() + .into(), + )) + .await + .unwrap(); + let _ack = ws.next().await.expect("connection_ack frame").unwrap(); + + let query = "subscription { SimpleEntity(limit: 1) { id } }"; + for id in ["one", "two"] { + ws.send(TMessage::Text( + serde_json::json!({ + "id": id, + "type": "subscribe", + "payload": { "query": query } + }) + .to_string() + .into(), + )) + .await + .unwrap(); + } + for _ in 0..2 { + let frame = tokio::time::timeout(Duration::from_secs(5), ws.next()) + .await + .expect("both subscribers receive the shared initial result") + .unwrap() + .unwrap(); + assert!(matches!(frame, TMessage::Text(_))); + } + + let read_count = || async { + server + .pool + .get() + .await + .unwrap() + .query_one("SELECT last_value FROM public.live_query_poll_count", &[]) + .await + .unwrap() + .get::<_, i64>(0) + }; + let before = read_count().await; + tokio::time::sleep(Duration::from_millis(750)).await; + let polls = read_count().await - before; + + assert!( + (2..=5).contains(&polls), + "two identical subscribers should produce one ~200ms poll loop, got {polls} database polls" + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn live_query_cohort_joiner_waits_for_a_fresh_poll() { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::tungstenite::http::HeaderValue; + use tokio_tungstenite::tungstenite::Message as TMessage; + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + // Make a scheduled poll impossible during the assertion window. A + // joining subscriber must request one shared refresh rather than replay + // the cohort's cached pre-insert payload. + env.ws_poll_interval_ms = 30_000; + let server = boot(env, Some(Duration::from_secs(20)), None).await; + + let mut request = format!("ws://127.0.0.1:{}/v1/graphql", server.port) + .into_client_request() + .unwrap(); + request.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_static("graphql-transport-ws"), + ); + let (mut ws, _) = tokio_tungstenite::connect_async(request) + .await + .expect("websocket handshake"); + ws.send(TMessage::Text( + serde_json::json!({"type": "connection_init"}) + .to_string() + .into(), + )) + .await + .unwrap(); + let _ack = ws.next().await.expect("connection_ack frame").unwrap(); + + let query = r#"subscription { SimpleEntity(where: {id: {_eq: "cohort-fresh"}}) { id value } }"#; + ws.send(TMessage::Text( + serde_json::json!({ + "id": "first", + "type": "subscribe", + "payload": { "query": query } + }) + .to_string() + .into(), + )) + .await + .unwrap(); + let first = tokio::time::timeout(Duration::from_secs(5), ws.next()) + .await + .expect("first subscriber receives the initial result") + .unwrap() + .unwrap(); + let TMessage::Text(first) = first else { + panic!("expected text data frame"); + }; + let first: serde_json::Value = serde_json::from_str(&first).unwrap(); + assert_eq!( + first["payload"]["data"]["SimpleEntity"], + serde_json::json!([]) + ); + + server + .pool + .get() + .await + .unwrap() + .execute( + r#"INSERT INTO public."SimpleEntity" (id, value) VALUES ('cohort-fresh', 'new')"#, + &[], + ) + .await + .unwrap(); + + ws.send(TMessage::Text( + serde_json::json!({ + "id": "joiner", + "type": "subscribe", + "payload": { "query": query } + }) + .to_string() + .into(), + )) + .await + .unwrap(); + let joined = tokio::time::timeout(Duration::from_secs(5), async { + loop { + let message = ws.next().await.expect("websocket remains open").unwrap(); + let TMessage::Text(text) = message else { + continue; + }; + let frame: serde_json::Value = serde_json::from_str(&text).unwrap(); + if frame["id"] == "joiner" { + return frame; + } + } + }) + .await + .expect("joiner should receive a fresh shared poll without waiting 30 seconds"); + assert_eq!( + joined["payload"]["data"]["SimpleEntity"], + serde_json::json!([{"id": "cohort-fresh", "value": "new"}]), + "a new subscriber must not receive the cohort's cached pre-subscription payload" + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn websocket_global_connection_limit_rejects_before_upgrade() { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::tungstenite::http::HeaderValue; + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + env.ws_max_connections = 1; + let server = boot(env, Some(Duration::from_secs(20)), None).await; + + let request = || { + let mut request = format!("ws://127.0.0.1:{}/v1/graphql", server.port) + .into_client_request() + .unwrap(); + request.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_static("graphql-transport-ws"), + ); + request + }; + let (_first, _) = tokio_tungstenite::connect_async(request()) + .await + .expect("first websocket handshake"); + let error = tokio_tungstenite::connect_async(request()) + .await + .expect_err("second websocket should be rejected before upgrade"); + let status = match error { + tokio_tungstenite::tungstenite::Error::Http(response) => response.status().as_u16(), + other => panic!("expected HTTP rejection, got {other}"), + }; + assert_eq!(status, 503); +} + +#[tokio::test(flavor = "multi_thread")] +async fn websocket_message_limit_is_explicitly_enforced() { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::tungstenite::http::HeaderValue; + use tokio_tungstenite::tungstenite::Message as TMessage; + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + env.ws_max_message_bytes = 128; + let server = boot(env, Some(Duration::from_secs(20)), None).await; + + let mut request = format!("ws://127.0.0.1:{}/v1/graphql", server.port) + .into_client_request() + .unwrap(); + request.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_static("graphql-transport-ws"), + ); + let (mut ws, _) = tokio_tungstenite::connect_async(request) + .await + .expect("websocket handshake"); + ws.send(TMessage::Text( + serde_json::json!({"type": "connection_init"}) + .to_string() + .into(), + )) + .await + .unwrap(); + let _ack = ws.next().await.expect("connection_ack frame").unwrap(); + + ws.send(TMessage::Text("x".repeat(129).into())) + .await + .unwrap(); + let closed = tokio::time::timeout(Duration::from_secs(2), ws.next()) + .await + .expect("oversized websocket message should close promptly"); + assert!( + matches!(&closed, Some(Ok(TMessage::Close(_))) | Some(Err(_)) | None), + "oversized frame must close instead of reaching the GraphQL protocol handler: {closed:?}" + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn black_holed_websocket_client_is_closed_within_30s() { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::tungstenite::http::HeaderValue; + use tokio_tungstenite::tungstenite::Message as TMessage; + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + // Fast ping interval so "2x interval" is well inside the 30s accept + // window without the test needing to wait near the production default. + env.ws_ping_interval_ms = 3_000; + let server = boot(env, Some(Duration::from_secs(20)), None).await; + + let mut request = format!("ws://127.0.0.1:{}/v1/graphql", server.port) + .into_client_request() + .unwrap(); + request.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_static("graphql-transport-ws"), + ); + let (mut ws, _) = tokio_tungstenite::connect_async(request) + .await + .expect("websocket handshake"); + + ws.send(TMessage::Text( + serde_json::json!({"type": "connection_init"}) + .to_string() + .into(), + )) + .await + .unwrap(); + let ack = ws.next().await.expect("connection_ack frame").unwrap(); + assert!( + matches!(ack, TMessage::Text(_)), + "expected a text connection_ack frame, got {ack:?}" + ); + + ws.send(TMessage::Text( + serde_json::json!({ + "id": "1", + "type": "subscribe", + "payload": { "query": SUBSCRIBE_QUERY } + }) + .to_string() + .into(), + )) + .await + .unwrap(); + // Confirm the subscription's background poll loop actually started + // before going quiet -- otherwise the test would trivially "pass" by + // never having started anything to detect. + let first = tokio::time::timeout(Duration::from_secs(5), ws.next()) + .await + .expect("subscription should push an initial live-query result") + .unwrap() + .unwrap(); + assert!(matches!(first, TMessage::Text(_))); + + // Simulate a frozen/black-holed client: stop driving the stream + // entirely for a while -- no `.next()` calls means no automatic pong + // replies and no traffic of any kind, without tearing down the TCP + // connection (a real black hole: the socket is fine, the peer just + // never reads or writes). ws_ping_interval_ms=3s means the server + // should give up by ~6s of silence; sleeping well past that before + // touching the stream again proves detection happened on its own, + // not because we kept polling and let tungstenite auto-pong for us. + let started = Instant::now(); + tokio::time::sleep(Duration::from_secs(9)).await; + + // Resume reading (bounded) to observe the close the server should + // already have sent while we were "frozen". By construction + // (`run_connection`'s cleanup aborts every operation task on close), + // that also stops the subscription's Postgres poll loop. + let closed = tokio::time::timeout(Duration::from_secs(15), async { + loop { + match ws.next().await { + Some(Ok(TMessage::Close(_))) | None => return true, + Some(Ok(_)) => continue, + Some(Err(_)) => return true, + } + } + }) + .await + .unwrap_or(false); + + assert_eq!( + (closed, started.elapsed() < Duration::from_secs(30)), + (true, true), + "server should close a black-holed client's connection within 30s" + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn shutdown_closes_websocket_subscriptions_cleanly() { + use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use tokio_tungstenite::tungstenite::http::HeaderValue; + use tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode; + use tokio_tungstenite::tungstenite::Message as TMessage; + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut server = boot(test_env(pg.port), Some(Duration::from_secs(20)), None).await; + + let mut request = format!("ws://127.0.0.1:{}/v1/graphql", server.port) + .into_client_request() + .unwrap(); + request.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_static("graphql-transport-ws"), + ); + let (mut ws, _) = tokio_tungstenite::connect_async(request) + .await + .expect("websocket handshake"); + + ws.send(TMessage::Text( + serde_json::json!({"type": "connection_init"}) + .to_string() + .into(), + )) + .await + .unwrap(); + let _ack = ws.next().await.expect("connection_ack frame").unwrap(); + ws.send(TMessage::Text( + serde_json::json!({ + "id": "1", + "type": "subscribe", + "payload": { "query": SUBSCRIBE_QUERY } + }) + .to_string() + .into(), + )) + .await + .unwrap(); + let first = tokio::time::timeout(Duration::from_secs(5), ws.next()) + .await + .expect("subscription should push an initial live-query result") + .unwrap() + .unwrap(); + assert!(matches!(first, TMessage::Text(_))); + + server.shutdown.take().unwrap().send(()).unwrap(); + + // Well before the 25s drain timeout, the server must send `complete` + // for the active subscription and then a 1001 (going away) close. + let started = Instant::now(); + let (saw_complete, close_code) = tokio::time::timeout(Duration::from_secs(10), async { + let mut saw_complete = false; + loop { + match ws.next().await { + Some(Ok(TMessage::Text(text))) => { + let frame: serde_json::Value = serde_json::from_str(&text).unwrap(); + if frame["type"] == "complete" && frame["id"] == "1" { + saw_complete = true; + } + } + Some(Ok(TMessage::Close(frame))) => { + return (saw_complete, frame.map(|f| u16::from(f.code))); + } + Some(Ok(_)) => {} + Some(Err(_)) | None => return (saw_complete, None), + } + } + }) + .await + .expect("server should close the websocket before the drain timeout"); + + assert_eq!( + ( + saw_complete, + close_code, + started.elapsed() < Duration::from_secs(10) + ), + (true, Some(u16::from(CloseCode::Away)), true), + "shutdown should complete active operations and close with 1001" + ); + + let serve_result = tokio::time::timeout(Duration::from_secs(15), &mut server.handle) + .await + .expect("server task should stop after connections close") + .expect("serve task should not panic"); + assert!(serve_result.is_ok()); +} + +#[tokio::test(flavor = "multi_thread")] +async fn aggregate_selection_count_null_args_errors_cleanly() { + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let mut env = test_env(pg.port); + env.aggregate_entities = vec!["Token".to_string()]; + let server = boot(env, Some(Duration::from_secs(20)), None).await; + + // `count`'s `columns` is a nullable list, but an explicit null literal + // is still a validation error — same rule as the aggregate bool_exp + // `arguments` case, just on the selection side (`{ T_aggregate { + // aggregate { count(columns: ...) } } }` instead of `where: {...}`). + // Wording and path confirmed live against Hasura 2.43.0. + let (status, body) = server + .graphql( + "{ Token_aggregate { aggregate { count(columns: null) } } }", + Duration::from_secs(10), + ) + .await; + assert_eq!( + (status, body), + ( + 200, + serde_json::json!({"errors": [{ + "message": "expected a list, but found null", + "extensions": { + "path": "$.selectionSet.Token_aggregate.selectionSet.aggregate.selectionSet.count.args.columns", + "code": "validation-failed" + } + }]}) + ) + ); + + // Same rule for `distinct` on the selection side. Wording and path + // confirmed live against Hasura 2.43.0. + let (status, body) = server + .graphql( + "{ Token_aggregate { aggregate { count(distinct: null) } } }", + Duration::from_secs(10), + ) + .await; + assert_eq!( + (status, body), + ( + 200, + serde_json::json!({"errors": [{ + "message": "expected a boolean for type 'Boolean', but found null", + "extensions": { + "path": "$.selectionSet.Token_aggregate.selectionSet.aggregate.selectionSet.count.args.distinct", + "code": "validation-failed" + } + }]}) + ) + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn json_field_null_path_errors_cleanly() { + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + let server = boot(test_env(pg.port), Some(Duration::from_secs(20)), None).await; + + // A json/jsonb field's `path` is a nullable String, but an explicit + // null literal is still a validation error, not "no path" (which is + // what omitting the argument means). Wording and path confirmed live + // against Hasura 2.43.0. + let (status, body) = server + .graphql( + "{ EntityWithAllTypes(limit: 1) { json(path: null) } }", + Duration::from_secs(10), + ) + .await; + assert_eq!( + (status, body), + ( + 200, + serde_json::json!({"errors": [{ + "message": "expected a string for type 'String', but found null", + "extensions": { + "path": "$.selectionSet.EntityWithAllTypes.selectionSet.json.args.path", + "code": "validation-failed" + } + }]}) + ) + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serve_becomes_healthy_once_postgres_starts_within_the_retry_budget() { + if skip_without_docker() { + return; + } + // Reserve the address but do not start Postgres on it yet -- then start + // it a few seconds in, exactly like a deploy that starts `envio serve` + // before its Postgres dependency is ready. + let port = free_port(); + let mut env = test_env(port); + env.startup_retry_budget_ms = 30_000; + + let pg_task = tokio::task::spawn_blocking(move || { + std::thread::sleep(Duration::from_secs(3)); + TestPg::start_on_port(port) + }); + + let pool = env.make_pg_pool().expect("pool"); + let started = Instant::now(); + // Proves the retry-then-recover behavior itself: `wait_for_pg` only + // needs Postgres reachable, not migrated, so this can succeed against + // an empty freshly-started container. + super::wait_for_pg(&pool, &env.pg_schema, env.startup_retry_budget_ms) + .await + .expect("wait_for_pg should succeed once Postgres comes up within budget"); + let retry_elapsed = started.elapsed(); + + // Schema readiness (migrations) is a separate deploy-ordering concern + // from Postgres reachability -- apply it now, then introspect fresh so + // the model actually has tables to serve. + apply_fixture(&pool, None).await; + let catalog = pg_catalog::introspect(&pool, &env.pg_schema).await.unwrap(); + + let project_root = concat!(env!("CARGO_MANIFEST_DIR"), "/../../scenarios/test_codegen"); + let paths = ParsedProjectPaths::new(project_root, "config.yaml").unwrap(); + let project_schema = ProjectSchema::load(&paths, &env).unwrap(); + let model = ServerModel::build(project_schema, catalog, &env).unwrap(); + let state = Arc::new(ServeState { + model, + pool: pool.clone(), + admin_secret: env.admin_secret.clone(), + query_timeout: Some(Duration::from_secs(20)), + healthz_timeout: Duration::from_millis(env.healthz_timeout_ms), + ws_ping_interval: Duration::from_millis(env.ws_ping_interval_ms), + ws_connection_init_timeout: Duration::from_millis(env.ws_connection_init_timeout_ms), + ws_max_connections: env.ws_max_connections, + ws_max_operations_per_connection: env.ws_max_operations_per_connection, + ws_max_operations: env.ws_max_operations, + ws_max_concurrent_polls: env.ws_max_concurrent_polls, + ws_poll_interval: Duration::from_millis(env.ws_poll_interval_ms), + ws_max_message_bytes: env.ws_max_message_bytes, + }); + + let http_port = { + let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + listener.local_addr().unwrap().port() + }; + let (_shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel::<()>(); + tokio::spawn(http::serve(state, "127.0.0.1", http_port, async move { + let _ = shutdown_rx.await; + })); + + let client = reqwest::Client::new(); + let mut healthy = false; + for _ in 0..20 { + if let Ok(res) = client + .get(format!("http://127.0.0.1:{http_port}/healthz")) + .timeout(Duration::from_secs(2)) + .send() + .await + { + if res.status().as_u16() == 200 { + healthy = true; + break; + } + } + tokio::time::sleep(Duration::from_millis(250)).await; + } + + let _pg = pg_task.await.unwrap(); + + assert_eq!( + (retry_elapsed < Duration::from_secs(30), healthy), + (true, true), + "serve should recover once Postgres starts within the retry budget and become healthy" + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn postgres_startup_errors_are_actionable() { + // Connection refusal needs no container and must identify the endpoint + // and the configuration knobs instead of exposing only a driver chain. + let mut unreachable = test_env(free_port()); + unreachable.startup_retry_budget_ms = 0; + let pool = unreachable.make_pg_pool().unwrap(); + let error = super::wait_for_pg(&pool, &unreachable.pg_schema, 0) + .await + .err() + .expect("unreachable PostgreSQL should fail"); + let message = super::postgres_startup_error(&unreachable, error).to_string(); + assert!(message.contains(&format!( + "Cannot connect to PostgreSQL at localhost:{}/envio-dev", + unreachable.pg_port + ))); + assert!(message.contains("ENVIO_PG_HOST")); + assert!(message.contains("ENVIO_PG_PORT")); + assert!(message.contains("ENVIO_PG_DATABASE")); + + if skip_without_docker() { + return; + } + let pg = TestPg::start(); + + let mut bad_password = test_env(pg.port); + bad_password.pg_password = "incorrect".to_string(); + bad_password.startup_retry_budget_ms = 20_000; + let pool = bad_password.make_pg_pool().unwrap(); + let error = super::wait_for_pg( + &pool, + &bad_password.pg_schema, + bad_password.startup_retry_budget_ms, + ) + .await + .err() + .expect("wrong PostgreSQL password should fail"); + let message = super::postgres_startup_error(&bad_password, error).to_string(); + assert!( + message.contains("rejected the credentials for user \"postgres\""), + "unexpected error: {message}" + ); + assert!(message.contains("ENVIO_PG_USER")); + assert!(message.contains("ENVIO_PG_PASSWORD")); + assert!(!message.contains("incorrect")); + + let mut missing_database = test_env(pg.port); + missing_database.pg_database = "missing_envio_database".to_string(); + missing_database.startup_retry_budget_ms = 20_000; + let pool = missing_database.make_pg_pool().unwrap(); + let error = super::wait_for_pg( + &pool, + &missing_database.pg_schema, + missing_database.startup_retry_budget_ms, + ) + .await + .err() + .expect("missing PostgreSQL database should fail"); + let message = super::postgres_startup_error(&missing_database, error).to_string(); + assert!( + message.contains("database \"missing_envio_database\" does not exist"), + "unexpected error: {message}" + ); + assert!(message.contains("ENVIO_PG_DATABASE")); +} diff --git a/packages/cli/src/serve/test_support.rs b/packages/cli/src/serve/test_support.rs new file mode 100644 index 0000000000..bec4432166 --- /dev/null +++ b/packages/cli/src/serve/test_support.rs @@ -0,0 +1,126 @@ +//! Shared docker-container test helpers for tests that need a throwaway +//! Postgres (TLS handshake test in env_config.rs, robustness/chaos tests in +//! robustness_tests.rs). Callers skip (not fail) when docker isn't +//! available, matching CI/dev environments that don't have it. + +use std::process::Command; + +pub fn docker_available() -> bool { + Command::new("docker") + .arg("info") + .output() + .map(|o| o.status.success()) + .unwrap_or(false) +} + +/// Returns true when the caller should skip because docker is missing. +/// With ENVIO_REQUIRE_DOCKER=1 (set in CI) a missing docker is a hard +/// failure instead — otherwise every docker-gated test would silently pass +/// vacuously if docker ever vanished from the runners. +pub fn skip_without_docker() -> bool { + if docker_available() { + return false; + } + if std::env::var("ENVIO_REQUIRE_DOCKER").as_deref() == Ok("1") { + panic!("docker is required (ENVIO_REQUIRE_DOCKER=1) but not available"); + } + eprintln!("skipping: docker is not available"); + true +} + +pub fn run(cmd: &mut Command) -> std::process::Output { + let output = cmd.output().expect("failed to run docker"); + assert!( + output.status.success(), + "docker command failed: {} {}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + output +} + +/// Picks a free TCP port by binding an ephemeral socket and immediately +/// releasing it -- used for docker `-p host:container` mappings that need a +/// fixed, predictable host port across container restarts (docker +/// re-allocates dynamic `-p 127.0.0.1::PORT` mappings on every restart, which +/// breaks tests that expect a stable address across a kill/start cycle). +pub fn free_port() -> u16 { + let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + listener.local_addr().unwrap().port() +} + +/// A unique-per-process-per-instant suffix for docker resource names +/// (containers, volumes) so concurrent test runs on the same machine never +/// collide. +pub fn unique_id() -> String { + format!( + "{}-{}", + std::process::id(), + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos() + ) +} + +/// A throwaway `postgres:16` container on a fixed host port, torn down on +/// drop. No TLS, no custom config -- for the TLS handshake test, see +/// env_config's own `TestTlsPostgres`, which needs a custom cert/config +/// mount this helper doesn't support. +pub struct TestPg { + name: String, + pub port: u16, +} + +impl TestPg { + pub fn start() -> TestPg { + Self::start_on_port(free_port()) + } + + /// Like `start`, but on a caller-chosen port instead of one freshly + /// picked here -- for tests that need to reserve the address before + /// Postgres actually exists on it (startup-retry tests). + pub fn start_on_port(port: u16) -> TestPg { + let name = format!("envio-serve-test-pg-{}", unique_id()); + run(Command::new("docker").args([ + "run", + "-d", + "--name", + &name, + "-e", + "POSTGRES_PASSWORD=testing", + "-e", + "POSTGRES_USER=postgres", + "-e", + "POSTGRES_DB=envio-dev", + "-p", + &format!("127.0.0.1:{port}:5432"), + "postgres:16", + ])); + + for _ in 0..60 { + let ready = Command::new("docker") + .args(["exec", &name, "pg_isready", "-U", "postgres"]) + .output() + .map(|o| o.status.success()) + .unwrap_or(false); + if ready { + return TestPg { name, port }; + } + std::thread::sleep(std::time::Duration::from_millis(500)); + } + panic!("test Postgres container did not become ready in time"); + } + + pub fn docker(&self, action: &str) { + run(Command::new("docker").args([action, &self.name])); + } +} + +impl Drop for TestPg { + fn drop(&mut self) { + let _ = Command::new("docker") + .args(["rm", "-f", &self.name]) + .output(); + } +} diff --git a/packages/cli/src/serve/ws.rs b/packages/cli/src/serve/ws.rs new file mode 100644 index 0000000000..6589888941 --- /dev/null +++ b/packages/cli/src/serve/ws.rs @@ -0,0 +1,1045 @@ +//! GraphQL-over-WebSocket subscriptions, supporting both protocols Hasura +//! serves on /v1/graphql: +//! - `graphql-transport-ws` (the modern graphql-ws protocol) +//! - `graphql-ws` (the legacy subscriptions-transport-ws protocol) +//! +//! Live queries behave like Hasura's multiplexed live queries observably: +//! an immediate first result, then a configurable poll loop that pushes a +//! new payload whenever the result changes. Identical compiled SQL, params, +//! and role share one poll loop across sockets. `_stream` roots advance +//! their cursor after every non-empty batch. +//! +//! Protocol differences pinned by the differential suite: +//! - subscribe/start message types (`subscribe` vs `start`), data types +//! (`next` vs `data`). +//! - error frame payloads: the modern protocol carries a bare ARRAY of +//! GraphQL errors; the legacy protocol wraps them in `{"errors": [...]}`. +//! - the legacy protocol emits `ka` keepalives. + +use super::exec::error::GraphQLError; +use super::exec::{self, ir, GraphQLRequest, Transport}; +use super::gql::schema_build::Role; +use super::http::AppState; +use axum::body::Bytes; +use axum::extract::ws::{Message, WebSocket, WebSocketUpgrade}; +use axum::http::{HeaderMap, StatusCode}; +use axum::response::IntoResponse; +use futures_util::sink::SinkExt; +use futures_util::stream::StreamExt; +use serde_json::json; +use std::collections::HashMap; +use std::hash::{Hash, Hasher}; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::{Arc, Mutex, Weak}; +use std::time::{Duration, Instant}; +use tokio::sync::{mpsc, watch, Notify, OwnedSemaphorePermit}; + +const KEEPALIVE_INTERVAL: Duration = Duration::from_secs(5); +/// Per-connection application queue. A peer that keeps the connection alive +/// while refusing to read must not turn server responses into unbounded RAM. +const OUTBOUND_QUEUE_CAPACITY: usize = 64; +/// How often the dead-connection check runs (independent of the +/// server-configured ping interval, so detection latency doesn't depend on +/// a large ENVIO_SERVE_WS_PING_INTERVAL_MS): a connection is only ever +/// declared dead on one of these ticks, so this bounds how far past "2x +/// ping interval" the actual close can lag. +const DEAD_CHECK_INTERVAL: Duration = Duration::from_secs(2); +/// Longest a graceful writer-task drain waits after the connection loop +/// exits before the task is force-aborted. Guards against a peer that +/// stopped reading (TCP send buffer full) leaving `ws_tx.send` blocked +/// forever on close. +const WRITER_DRAIN_TIMEOUT: Duration = Duration::from_secs(2); +/// Consecutive connection-level Postgres failures a subscription survives +/// (silently retrying on the poll interval) before it gives up with a +/// terminal error frame. Without this, any 1-second Postgres blip +/// permanently kills every active subscription — most graphql-ws clients +/// treat an error frame as terminal and never resubscribe. +const SUBSCRIPTION_TRANSIENT_RETRIES: u32 = 5; +static NEXT_CONNECTION_ID: AtomicU64 = AtomicU64::new(1); + +#[derive(Clone, Copy, PartialEq, Eq)] +enum Protocol { + /// graphql-transport-ws + Modern, + /// subscriptions-transport-ws (legacy; subprotocol name "graphql-ws") + Legacy, +} + +impl Protocol { + fn data_type(&self) -> &'static str { + match self { + Protocol::Modern => "next", + Protocol::Legacy => "data", + } + } + fn start_type(&self) -> &'static str { + match self { + Protocol::Modern => "subscribe", + Protocol::Legacy => "start", + } + } + fn stop_type(&self) -> &'static str { + match self { + Protocol::Modern => "complete", + Protocol::Legacy => "stop", + } + } +} + +pub fn handle_upgrade( + state: AppState, + headers: HeaderMap, + upgrade: WebSocketUpgrade, +) -> axum::response::Response { + let connection_permit = match state.ws_connection_slots.clone().try_acquire_owned() { + Ok(permit) => permit, + Err(_) => { + tracing::warn!("websocket connection rejected: global connection limit reached"); + return ( + StatusCode::SERVICE_UNAVAILABLE, + "websocket connection limit reached", + ) + .into_response(); + } + }; + // Hasura also reads auth from the upgrade request's HTTP headers, not + // only the connection_init payload; capture them here so init can fall + // back to them. + let upgrade_auth = UpgradeAuth { + admin_secret: headers + .get("x-hasura-admin-secret") + .and_then(|v| v.to_str().ok()) + .map(String::from), + role: headers + .get("x-hasura-role") + .and_then(|v| v.to_str().ok()) + .map(String::from), + }; + upgrade + .max_message_size(state.serve.ws_max_message_bytes) + .max_frame_size(state.serve.ws_max_message_bytes) + .protocols(["graphql-transport-ws", "graphql-ws"]) + .on_upgrade(move |socket| async move { + // The permit is held across the entire upgraded connection and + // released on every exit path, including panics/cancellation. + let _connection_permit = connection_permit; + let protocol = match socket.protocol().and_then(|p| p.to_str().ok()) { + Some("graphql-transport-ws") => Protocol::Modern, + _ => Protocol::Legacy, + }; + run_connection(state, socket, protocol, upgrade_auth).await; + }) + .into_response() +} + +struct UpgradeAuth { + admin_secret: Option, + role: Option, +} + +/// Bounded, non-blocking output shared by connection and operation tasks. +/// Queue overflow wakes the connection loop, which tears down the socket and +/// aborts all pollers instead of dropping arbitrary GraphQL frames. +#[derive(Clone)] +struct Outbound { + tx: mpsc::Sender, + overflow: Arc, +} + +impl Outbound { + fn channel(capacity: usize) -> (Outbound, mpsc::Receiver) { + let (tx, rx) = mpsc::channel(capacity); + ( + Outbound { + tx, + overflow: Arc::new(Notify::new()), + }, + rx, + ) + } + + fn send(&self, message: Message) -> Result<(), ()> { + match self.tx.try_send(message) { + Ok(()) => Ok(()), + Err(mpsc::error::TrySendError::Full(_)) => { + self.overflow.notify_one(); + Err(()) + } + Err(mpsc::error::TrySendError::Closed(_)) => { + self.overflow.notify_one(); + Err(()) + } + } + } +} + +#[derive(Clone)] +enum LiveQueryEvent { + Pending, + Data { refresh_epoch: u64, root: Arc }, + Error(Arc), +} + +struct LiveQueryCohort { + events: watch::Sender, + refresh: Arc, +} + +struct LiveQueryRefresh { + wake: Notify, + epoch: AtomicU64, +} + +struct LiveQuerySubscription { + alias: String, + events: watch::Receiver, + /// The cohort result visible when this subscriber joined is historical. + /// Its first payload must come from a later shared poll. + required_refresh_epoch: u64, + /// Keeps the cohort discoverable while this subscriber is alive. The + /// poll task itself holds only a Weak, so it stops when the last + /// receiver leaves. + _cohort: Arc, +} + +/// Server-wide exact-key live-query deduplication. Matching means compiled +/// SQL + bound params + role, which is stronger and cheaper than comparing +/// raw GraphQL text and naturally coalesces formatting and alias changes. +#[derive(Clone, Default)] +pub(crate) struct LiveQueryRegistry { + cohorts: Arc>>>, +} + +impl LiveQueryRegistry { + fn subscribe(&self, state: &AppState, live: exec::CompiledLiveQuery) -> LiveQuerySubscription { + let alias = live.alias.clone(); + let key = live.key.clone(); + let mut live = Some(live); + let mut new_cohort = None; + + let subscription = { + let mut cohorts = self.cohorts.lock().expect("live-query registry poisoned"); + if let Some(cohort) = cohorts.get(&key).and_then(Weak::upgrade) { + tracing::debug!(cohort = key.stable_hash(), "joining live-query cohort"); + let events = cohort.events.subscribe(); + let required_refresh_epoch = + cohort.refresh.epoch.fetch_add(1, Ordering::AcqRel) + 1; + // Notify permits coalesce, so many simultaneous joiners cause + // one shared refresh instead of one query per subscriber. + cohort.refresh.wake.notify_one(); + LiveQuerySubscription { + alias, + events, + required_refresh_epoch, + _cohort: cohort, + } + } else { + let (events, receiver) = watch::channel(LiveQueryEvent::Pending); + let refresh = Arc::new(LiveQueryRefresh { + wake: Notify::new(), + epoch: AtomicU64::new(0), + }); + let cohort = Arc::new(LiveQueryCohort { + events: events.clone(), + refresh: refresh.clone(), + }); + let weak = Arc::downgrade(&cohort); + cohorts.insert(key.clone(), weak.clone()); + new_cohort = Some((events, refresh, weak, live.take().unwrap())); + tracing::debug!(cohort = key.stable_hash(), "starting live-query cohort"); + LiveQuerySubscription { + alias, + events: receiver, + required_refresh_epoch: 0, + _cohort: cohort, + } + } + }; + + if let Some((events, refresh, weak, live)) = new_cohort { + let registry = self.clone(); + let state = state.clone(); + tokio::spawn(async move { + run_live_query_cohort(registry, key, weak, state, live, events, refresh).await; + }); + } + subscription + } + + fn remove_if_same(&self, key: &exec::LiveQueryKey, cohort: &Weak) { + let mut cohorts = self.cohorts.lock().expect("live-query registry poisoned"); + if cohorts + .get(key) + .is_some_and(|current| Weak::ptr_eq(current, cohort)) + { + cohorts.remove(key); + } + } +} + +async fn run_live_query_cohort( + registry: LiveQueryRegistry, + key: exec::LiveQueryKey, + cohort: Weak, + state: AppState, + live: exec::CompiledLiveQuery, + events: watch::Sender, + refresh: Arc, +) { + let poll_interval = state.serve.ws_poll_interval; + let jitter = cohort_jitter(&key, poll_interval); + let first_tick = tokio::time::Instant::now() + poll_interval + jitter; + let mut ticks = tokio::time::interval_at(first_tick, poll_interval); + ticks.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); + let mut published_refresh_epoch = 0u64; + let mut last_payload: Option> = None; + let mut consecutive_failures = 0u32; + + loop { + let poll_permit = tokio::select! { + _ = events.closed() => break, + permit = state.ws_poll_slots.acquire() => match permit { + Ok(permit) => permit, + Err(_) => break, + }, + }; + // A join request that arrives after this load is intentionally not + // satisfied by the in-flight query: the follow-up notify triggers a + // poll that started after the subscriber joined. + let poll_refresh_epoch = refresh.epoch.load(Ordering::Acquire); + let result = exec::poll_live_query(&state.serve, &live).await; + drop(poll_permit); + + match result { + Ok(body) => { + consecutive_failures = 0; + if last_payload.as_deref() != Some(body.as_str()) + || poll_refresh_epoch > published_refresh_epoch + { + let root: Arc = body.into(); + last_payload = Some(root.clone()); + published_refresh_epoch = poll_refresh_epoch; + // Unchanged scheduled polls stay inside the cohort and + // wake nobody. A post-join refresh is published even if + // its body is identical, and subscribers suppress it + // unless they are the joiner waiting for this epoch. + if events + .send(LiveQueryEvent::Data { + refresh_epoch: poll_refresh_epoch, + root, + }) + .is_err() + { + break; + } + } + } + Err(error) => { + if !error.is_transient_infra() + || consecutive_failures >= SUBSCRIPTION_TRANSIENT_RETRIES + { + let _ = events.send(LiveQueryEvent::Error(Arc::new(error))); + break; + } + consecutive_failures += 1; + } + } + + tokio::select! { + _ = events.closed() => break, + _ = ticks.tick() => {} + _ = refresh.wake.notified() => {} + } + } + + registry.remove_if_same(&key, &cohort); + tracing::debug!(cohort = key.stable_hash(), "stopped live-query cohort"); +} + +fn cohort_jitter(key: &exec::LiveQueryKey, interval: Duration) -> Duration { + let max_jitter_ms = (interval.as_millis() as u64 / 4).max(1); + Duration::from_millis(key.stable_hash() % max_jitter_ms) +} + +struct Connection { + id: u64, + state: AppState, + protocol: Protocol, + sender: Outbound, + upgrade_auth: UpgradeAuth, + role: Option, + /// Live operations by client-assigned id; sending on the channel stops + /// the poll task. + operations: HashMap>, + operation_done: mpsc::UnboundedSender, +} + +async fn run_connection( + state: AppState, + socket: WebSocket, + protocol: Protocol, + upgrade_auth: UpgradeAuth, +) { + tracing::debug!("websocket connection opened"); + let ping_interval = state.serve.ws_ping_interval; + let dead_after = ping_interval * 2; + let init_timeout = state.serve.ws_connection_init_timeout; + let mut shutdown = state.shutdown.clone(); + + let (mut ws_tx, mut ws_rx) = socket.split(); + let (outbound, mut rx) = Outbound::channel(OUTBOUND_QUEUE_CAPACITY); + let overflow = outbound.overflow.clone(); + let (operation_done, mut operation_done_rx) = mpsc::unbounded_channel::(); + + let mut writer = tokio::spawn(async move { + while let Some(msg) = rx.recv().await { + if ws_tx.send(msg).await.is_err() { + break; + } + } + }); + + let mut conn = Connection { + id: NEXT_CONNECTION_ID.fetch_add(1, Ordering::Relaxed), + state, + protocol, + sender: outbound, + upgrade_auth, + role: None, + operations: HashMap::new(), + operation_done, + }; + + let init_deadline = tokio::time::sleep(init_timeout); + tokio::pin!(init_deadline); + + let mut keepalive = tokio::time::interval(KEEPALIVE_INTERVAL); + keepalive.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); + + // Server-driven protocol-level ping, independent of either GraphQL + // sub-protocol's own app-level keepalive frames: a client that stops + // reading (frozen, network black hole) never returns a pong or any + // other traffic, so the connection -- and every subscription poll task + // it's keeping alive -- gets torn down instead of running against + // Postgres forever in the background. + let mut dead_check = tokio::time::interval(std::cmp::min(ping_interval, DEAD_CHECK_INTERVAL)); + dead_check.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); + let mut last_activity = Instant::now(); + let mut last_ping_sent = Instant::now(); + + loop { + tokio::select! { + _ = &mut init_deadline, if conn.role.is_none() => { + tracing::warn!("closing websocket: connection_init timeout"); + let _ = conn.sender.send(Message::Close(Some(axum::extract::ws::CloseFrame { + code: 4408, + reason: "Connection initialisation timeout".into(), + }))); + break; + } + _ = overflow.notified() => { + tracing::warn!("closing websocket: outbound queue limit reached"); + break; + } + Some(id) = operation_done_rx.recv() => { + conn.operations.remove(&id); + } + _ = keepalive.tick() => { + if conn.protocol == Protocol::Legacy && conn.role.is_some() { + let _ = conn.sender.send(Message::Text("{\"type\":\"ka\"}".into())); + } + } + // Graceful shutdown: finish each active operation with a + // `complete` frame, then a 1001 close, so clients see a clean + // end instead of a dropped socket at the drain timeout. + // The extra async block drops watch's non-Send read guard + // before the branch value is produced, keeping the whole + // connection future Send. + _ = async { let _ = shutdown.wait_for(|stopping| *stopping).await; } => { + for (id, task) in conn.operations.drain() { + task.abort(); + send_frame(&conn.sender, "complete", &id, None); + } + let _ = conn.sender.send(Message::Close(Some(axum::extract::ws::CloseFrame { + code: 1001, + reason: "going away".into(), + }))); + break; + } + _ = dead_check.tick() => { + let now = Instant::now(); + if now.duration_since(last_activity) > dead_after { + tracing::warn!("closing websocket, no pong/traffic for {:?}", now.duration_since(last_activity)); + let _ = conn.sender.send(Message::Close(Some(axum::extract::ws::CloseFrame { + code: 4408, + reason: "ping timeout".into(), + }))); + break; + } + if now.duration_since(last_ping_sent) >= ping_interval { + last_ping_sent = now; + let _ = conn.sender.send(Message::Ping(Bytes::new())); + } + } + incoming = ws_rx.next() => { + let Some(Ok(msg)) = incoming else { break }; + last_activity = Instant::now(); + while let Ok(id) = operation_done_rx.try_recv() { + conn.operations.remove(&id); + } + match msg { + Message::Text(text) => { + if handle_frame(&mut conn, &text).await.is_err() { + break; + } + } + Message::Ping(_) | Message::Pong(_) => {} + Message::Close(_) => break, + Message::Binary(_) => {} + } + } + } + } + + tracing::debug!("websocket connection closed"); + for (_, task) in conn.operations.drain() { + task.abort(); + } + drop(conn); + if tokio::time::timeout(WRITER_DRAIN_TIMEOUT, &mut writer) + .await + .is_err() + { + writer.abort(); + } +} + +/// Returns Err to close the connection. +async fn handle_frame(conn: &mut Connection, text: &str) -> Result<(), ()> { + let (frame, number_originals) = + match exec::validate::json_numbers::parse_value_preserving_numbers(text) { + Ok(v) => v, + Err(_) => { + return if conn.protocol == Protocol::Modern { + Err(()) + } else { + Ok(()) + } + } + }; + let frame_type = frame.get("type").and_then(|t| t.as_str()).unwrap_or(""); + + match frame_type { + "connection_init" => { + if conn.role.is_some() { + return match conn.protocol { + Protocol::Modern => { + let _ = + conn.sender + .send(Message::Close(Some(axum::extract::ws::CloseFrame { + code: 4429, + reason: "Too many initialisation requests".into(), + }))); + Err(()) + } + Protocol::Legacy => { + send_json( + conn, + json!({"type": "connection_error", "payload": {"message": "Too many initialisation requests"}}), + ); + Err(()) + } + }; + } + let payload_headers = frame.get("payload").and_then(|p| p.get("headers")); + // Client-sent payload "headers" keys are arbitrary strings, not + // normalized HTTP headers -- match them case-insensitively like + // Hasura does. + let payload_header = |name: &str| -> Option<&str> { + payload_headers.and_then(|h| h.as_object()).and_then(|map| { + map.iter() + .find(|(k, _)| k.eq_ignore_ascii_case(name)) + .and_then(|(_, v)| v.as_str()) + }) + }; + // Auth comes from the init payload when present, falling back + // per-header to the upgrade request's HTTP headers (Hasura + // accepts both sources; the payload is the protocol-native one, + // so it wins on conflict). + let secret = payload_header("x-hasura-admin-secret") + .or(conn.upgrade_auth.admin_secret.as_deref()); + let requested_role = + payload_header("x-hasura-role").or(conn.upgrade_auth.role.as_deref()); + let role = match super::http::resolve_role_values( + secret, + requested_role, + &conn.state.serve.admin_secret, + ) { + Ok(role) => role, + Err(err) => { + tracing::debug!("websocket connection_init rejected: {}", err.message); + match conn.protocol { + Protocol::Modern => { + // graphql-ws: reject with a close frame. + let _ = conn.sender.send(Message::Close(Some( + axum::extract::ws::CloseFrame { + code: 4403, + reason: "Forbidden".into(), + }, + ))); + return Err(()); + } + Protocol::Legacy => { + send_json( + conn, + json!({"type": "connection_error", "payload": err.response_body()}), + ); + return Err(()); + } + } + } + }; + conn.role = Some(role); + send_json(conn, json!({"type": "connection_ack"})); + if conn.protocol == Protocol::Legacy { + let _ = conn.sender.send(Message::Text("{\"type\":\"ka\"}".into())); + } + Ok(()) + } + "ping" => { + send_json(conn, json!({"type": "pong"})); + Ok(()) + } + "pong" => Ok(()), + "connection_terminate" => Err(()), + t if t == conn.protocol.start_type() => { + let Some(role) = conn.role else { + // Operations before connection_init. + return match conn.protocol { + Protocol::Modern => { + let _ = + conn.sender + .send(Message::Close(Some(axum::extract::ws::CloseFrame { + code: 4401, + reason: "Unauthorized".into(), + }))); + Err(()) + } + Protocol::Legacy => Ok(()), + }; + }; + let Some(id) = frame.get("id").and_then(|v| v.as_str()).map(String::from) else { + return Ok(()); + }; + if conn.operations.contains_key(&id) { + if conn.protocol == Protocol::Modern { + let _ = conn + .sender + .send(Message::Close(Some(axum::extract::ws::CloseFrame { + code: 4409, + reason: format!("Subscriber for {id} already exists").into(), + }))); + return Err(()); + } + return Ok(()); + } + if conn.operations.len() >= conn.state.serve.ws_max_operations_per_connection { + tracing::warn!( + limit = conn.state.serve.ws_max_operations_per_connection, + "websocket operation rejected: per-connection limit reached" + ); + let _ = conn + .sender + .send(Message::Close(Some(axum::extract::ws::CloseFrame { + code: 1008, + reason: "websocket operation limit reached".into(), + }))); + return Err(()); + } + let operation_permit = match conn.state.ws_operation_slots.clone().try_acquire_owned() { + Ok(permit) => permit, + Err(_) => { + tracing::warn!("websocket operation rejected: global limit reached"); + let _ = conn + .sender + .send(Message::Close(Some(axum::extract::ws::CloseFrame { + code: 1013, + reason: "global websocket operation limit reached".into(), + }))); + return Err(()); + } + }; + let payload = frame.get("payload").cloned().unwrap_or(json!({})); + let variables = payload.get("variables").cloned(); + let variable_number_originals = + if matches!(variables, Some(serde_json::Value::Object(_))) { + number_originals + } else { + Default::default() + }; + let request = GraphQLRequest { + query: payload + .get("query") + .and_then(|q| q.as_str()) + .map(String::from), + variables, + operation_name: payload + .get("operationName") + .and_then(|o| o.as_str()) + .map(String::from), + variable_number_originals, + }; + start_operation(conn, role, id, request, operation_permit); + Ok(()) + } + t if t == conn.protocol.stop_type() => { + if let Some(id) = frame.get("id").and_then(|v| v.as_str()) { + if let Some(task) = conn.operations.remove(id) { + tracing::debug!(op = %id, "websocket operation stopped"); + task.abort(); + // The client asked to stop; the legacy protocol echoes a + // complete frame, the modern one does not. + if conn.protocol == Protocol::Legacy { + send_json(conn, json!({"type": "complete", "id": id})); + } + } + } + Ok(()) + } + _ => Ok(()), + } +} + +fn send_json(conn: &Connection, value: serde_json::Value) { + let _ = conn.sender.send(Message::Text(value.to_string().into())); +} + +fn start_operation( + conn: &mut Connection, + role: Role, + id: String, + request: GraphQLRequest, + operation_permit: OwnedSemaphorePermit, +) { + let state = conn.state.clone(); + let protocol = conn.protocol; + let sender = conn.sender.clone(); + let op_id = id.clone(); + let operation_done = conn.operation_done.clone(); + let connection_id = conn.id; + + tracing::debug!(op = %id, "websocket operation started"); + let task = tokio::spawn(async move { + let _operation_permit = operation_permit; + run_operation( + state, + protocol, + role, + connection_id, + op_id.clone(), + request, + sender, + ) + .await; + let _ = operation_done.send(op_id); + }); + conn.operations.insert(id, task); +} + +fn send_frame(sender: &Outbound, frame_type: &str, id: &str, payload_json: Option<&str>) { + let mut out = String::with_capacity(64 + payload_json.map_or(0, |p| p.len())); + out.push_str("{\"type\":"); + out.push_str(&serde_json::to_string(frame_type).unwrap()); + out.push_str(",\"id\":"); + out.push_str(&serde_json::to_string(id).unwrap()); + if let Some(p) = payload_json { + out.push_str(",\"payload\":"); + out.push_str(p); + } + out.push('}'); + let _ = sender.send(Message::Text(out.into())); +} + +fn send_error(sender: &Outbound, protocol: Protocol, id: &str, error: &GraphQLError) { + let payload = match protocol { + // Modern protocol: a bare array of GraphQL errors. + Protocol::Modern => serde_json::Value::Array(vec![error.to_json()]).to_string(), + // Legacy protocol: wrapped in an errors object. + Protocol::Legacy => error.response_body().to_string(), + }; + send_frame(sender, "error", id, Some(&payload)); +} + +async fn run_operation( + state: AppState, + protocol: Protocol, + role: Role, + connection_id: u64, + id: String, + request: GraphQLRequest, + sender: Outbound, +) { + let schema = state.schemas.for_role(role); + let operation = + match exec::validate::plan_request(&state.serve.model, schema, &request, Transport::Ws) { + Ok(op) => op, + Err(e) => { + send_error(&sender, protocol, &id, &e); + return; + } + }; + + match operation.kind { + ir::OperationKind::Query => { + match exec::execute_operation(&state.serve, schema, &operation).await { + Ok(body) => { + send_frame(&sender, protocol.data_type(), &id, Some(&body)); + send_frame(&sender, "complete", &id, None); + } + Err(e) => send_error(&sender, protocol, &id, &e), + } + } + ir::OperationKind::Subscription => { + run_subscription( + state.clone(), + protocol, + role, + connection_id, + id, + operation, + sender, + ) + .await + } + } +} + +/// Live query / stream loop: emit the first result immediately, then poll, +/// pushing only when the payload changes (streams: when a batch is +/// non-empty, advancing the cursor). +async fn run_subscription( + state: AppState, + protocol: Protocol, + role: Role, + connection_id: u64, + id: String, + mut operation: ir::Operation, + sender: Outbound, +) { + let schema = state.schemas.for_role(role); + let is_stream = matches!( + operation.root_fields.first(), + Some(ir::RootField::Table(ir::TableRoot { + kind: ir::TableRootKind::Stream { .. }, + .. + })) + ); + + // Ordinary table subscriptions use one server-wide poll loop per exact + // compiled SQL/params/role key. Stream subscriptions retain an + // independent cursor and therefore cannot join an ordinary cohort. + if !is_stream { + if let Some(live) = exec::compile_live_query(&state.serve.model.pg_schema, role, &operation) + { + let subscription = state.live_queries.subscribe(&state, live); + run_live_query_subscription(protocol, id, sender, subscription).await; + return; + } + } + + let mut last_payload: Option = None; + let mut consecutive_failures: u32 = 0; + // Compiles the stream SQL once, swapping cursor params per poll. + let mut stream_poller = exec::StreamPoller::new(); + let poll_interval = state.serve.ws_poll_interval; + let jitter = subscription_jitter(connection_id, &id, poll_interval); + let first_tick = tokio::time::Instant::now() + poll_interval + jitter; + let mut ticks = tokio::time::interval_at(first_tick, poll_interval); + ticks.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); + loop { + let poll_permit = match state.ws_poll_slots.acquire().await { + Ok(permit) => permit, + Err(_) => return, + }; + let result = if is_stream { + match stream_poller.poll(&state.serve, &mut operation).await { + // Non-empty batch: emit; the poller advanced the cursor. + Ok(Some(body)) => { + send_frame(&sender, protocol.data_type(), &id, Some(&body)); + Ok(()) + } + Ok(None) => Ok(()), // empty batch: keep waiting + Err(e) => Err(e), + } + } else { + match exec::execute_operation(&state.serve, schema, &operation).await { + Ok(body) => { + if last_payload.as_deref() != Some(body.as_str()) { + send_frame(&sender, protocol.data_type(), &id, Some(&body)); + last_payload = Some(body); + } + Ok(()) + } + Err(e) => Err(e), + } + }; + drop(poll_permit); + match result { + Ok(()) => consecutive_failures = 0, + Err(e) => { + // Connection-level failures (Postgres down/restarting, pool + // exhausted) self-heal: keep polling and re-attempt so the + // stream resumes when Postgres does. Deterministic query + // errors terminate immediately, matching Hasura. + if !e.is_transient_infra() || consecutive_failures >= SUBSCRIPTION_TRANSIENT_RETRIES + { + send_error(&sender, protocol, &id, &e); + return; + } + consecutive_failures += 1; + } + } + ticks.tick().await; + } +} + +async fn run_live_query_subscription( + protocol: Protocol, + id: String, + sender: Outbound, + subscription: LiveQuerySubscription, +) { + let LiveQuerySubscription { + alias, + mut events, + required_refresh_epoch, + _cohort, + } = subscription; + let mut last_payload: Option> = None; + + loop { + let event = events.borrow_and_update().clone(); + match event { + LiveQueryEvent::Pending => {} + LiveQueryEvent::Data { + refresh_epoch, + root, + } if refresh_epoch >= required_refresh_epoch + && last_payload.as_deref() != Some(root.as_ref()) => + { + let alias_json = serde_json::to_string(&alias).unwrap(); + let mut body = String::with_capacity(alias_json.len() + root.len() + 13); + body.push_str("{\"data\":{"); + body.push_str(&alias_json); + body.push(':'); + body.push_str(&root); + body.push_str("}}"); + send_frame(&sender, protocol.data_type(), &id, Some(&body)); + last_payload = Some(root); + } + LiveQueryEvent::Data { .. } => {} + LiveQueryEvent::Error(error) => { + send_error(&sender, protocol, &id, &error); + return; + } + } + + if events.changed().await.is_err() { + return; + } + } +} + +fn subscription_jitter(connection_id: u64, operation_id: &str, interval: Duration) -> Duration { + let max_jitter_ms = (interval.as_millis() as u64 / 4).max(1); + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + connection_id.hash(&mut hasher); + operation_id.hash(&mut hasher); + Duration::from_millis(hasher.finish() % max_jitter_ms) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn subscribe_payload_variables_preserve_lossy_numbers() { + let text = r#"{"id":"1","type":"subscribe","payload":{"query":"q","variables":{"big":99999999999999999999999,"small":1.5}}}"#; + let (frame, originals) = + exec::validate::json_numbers::parse_value_preserving_numbers(text).unwrap(); + let vars = &frame["payload"]["variables"]; + let sentinel_bits = vars["big"].as_f64().unwrap().to_bits().to_string(); + assert_eq!( + ( + originals + .get(&sentinel_bits.parse::().unwrap()) + .map(String::as_str), + vars["small"].as_f64(), + vars["big"].as_i64(), + ), + (Some("99999999999999999999999"), Some(1.5), None) + ); + } + + #[test] + fn payload_without_lossy_numbers_is_untouched() { + let text = r#"{"id":"1","type":"subscribe","payload":{"query":"q","variables":{"n":42}}}"#; + let (frame, originals) = + exec::validate::json_numbers::parse_value_preserving_numbers(text).unwrap(); + assert_eq!(frame["payload"]["variables"], json!({"n": 42})); + assert!(originals.is_empty()); + } + + #[test] + fn client_number_metadata_key_is_not_trusted() { + let text = r#"{"id":"1","type":"subscribe","payload":{"query":"q","variables":{"v":1.5,"\u0001variable number originals":{"4609434218613702656":"999999999999999999"}}}}"#; + let (frame, originals) = + exec::validate::json_numbers::parse_value_preserving_numbers(text).unwrap(); + assert!(originals.is_empty()); + assert!(frame["payload"]["variables"] + .get("\u{1}variable number originals") + .is_some()); + } + + #[test] + fn websocket_frame_preserves_out_of_f64_range_numbers() { + let text = r#"{"id":"1","type":"subscribe","payload":{"query":"q","variables":{"n":1e400,"j":{"nested":-9e999}}}}"#; + let (frame, originals) = + exec::validate::json_numbers::parse_value_preserving_numbers(text).unwrap(); + let variables = &frame["payload"]["variables"]; + for (value, expected) in [ + (&variables["n"], "1e400"), + (&variables["j"]["nested"], "-9e999"), + ] { + let bits = value.as_f64().unwrap().to_bits(); + assert_eq!(originals.get(&bits).map(String::as_str), Some(expected)); + } + assert!( + exec::validate::json_numbers::parse_value_preserving_numbers( + r#"{"id":"1","type":"subscribe","payload":{"variables":{"n":1e}}}"# + ) + .is_err() + ); + } + + #[tokio::test] + async fn outbound_queue_is_bounded_and_reports_overflow() { + let (sender, mut receiver) = Outbound::channel(1); + sender + .send(Message::Text("first".into())) + .expect("first message fits"); + assert!(sender.send(Message::Text("second".into())).is_err()); + tokio::time::timeout(Duration::from_millis(50), sender.overflow.notified()) + .await + .expect("overflow notification is retained"); + assert_eq!(receiver.recv().await, Some(Message::Text("first".into()))); + } + + #[test] + fn subscription_jitter_is_stable_and_bounded() { + let interval = Duration::from_secs(1); + let a = subscription_jitter(7, "operation-a", interval); + assert_eq!(a, subscription_jitter(7, "operation-a", interval)); + assert!(a < Duration::from_millis(250)); + } +} diff --git a/packages/cli/src/type_schema.rs b/packages/cli/src/type_schema.rs index 17fae8e135..66aa123e20 100644 --- a/packages/cli/src/type_schema.rs +++ b/packages/cli/src/type_schema.rs @@ -100,7 +100,7 @@ impl TypeDecl { }; format!( "{type_name}{parameters} = {type_expr}", - type_name = &self.name, + type_name = self.name, type_expr = self.type_expr ) } @@ -124,7 +124,7 @@ impl TypeDecl { }; format!( "type {name}{parameters} = {type_expr};", - name = &self.name, + name = self.name, type_expr = self.type_expr.to_ts_type_string_with_namespace(ns) ) } @@ -144,7 +144,7 @@ impl TypeDecl { let args_joined = arguments.join(", "); format!("<{args_joined}>") }; - Ok(format!("{}{arguments_code}", &self.name)) + Ok(format!("{}{arguments_code}", self.name)) } } @@ -420,7 +420,7 @@ impl TypeIdent { format!("{{{inner}}}") } Self::SchemaEnum(enum_name) => { - format!("Enums.{}.t", &enum_name.capitalized) + format!("Enums.{}.t", enum_name.capitalized) } // Lowercase generic params because of the issue https://github.com/rescript-lang/rescript-compiler/issues/6759 Self::GenericParam(name) => format!("'{}", name.to_lowercase()), @@ -563,7 +563,7 @@ impl TypeIdent { Self::SchemaEnum(enum_name) => { // References the file-level `Enums` lookup table emitted by // codegen_templates.rs::wrap_envio_module_augmentation. - format!("Enums[\"{}\"]", &enum_name.original) + format!("Enums[\"{}\"]", enum_name.original) } Self::GenericParam(name) => name.clone(), Self::TypeApplication { @@ -597,7 +597,7 @@ impl TypeIdent { Self::Array(_) => "[]".to_string(), Self::Option(_) => "None".to_string(), Self::SchemaEnum(enum_name) => { - format!("Enums.{}.default", &enum_name.capitalized) + format!("Enums.{}.default", enum_name.capitalized) } Self::Tuple(inner_types) => { let inner_types_str = inner_types @@ -681,7 +681,7 @@ impl TypeIdent { Self::Array(_) => "[]".to_string(), Self::Option(_) => "null".to_string(), Self::SchemaEnum(enum_name) => { - format!("{}Default", &enum_name.uncapitalized) + format!("{}Default", enum_name.uncapitalized) } Self::Tuple(inner_types) => { let inner_types_str = inner_types diff --git a/packages/cli/test/configs/serve-legacy-2.21.5-custom-schema.yaml b/packages/cli/test/configs/serve-legacy-2.21.5-custom-schema.yaml new file mode 100644 index 0000000000..096c52e309 --- /dev/null +++ b/packages/cli/test/configs/serve-legacy-2.21.5-custom-schema.yaml @@ -0,0 +1,9 @@ +# v2.21.5-era config with an explicit custom `schema` path. +name: legacy_custom_schema +schema: ./schemas/gravatar-schema.graphql +unordered_multichain_mode: true +event_decoder: hypersync-client +networks: + - id: 1 + start_block: 0 + contracts: [] diff --git a/packages/cli/test/configs/serve-legacy-2.21.5.yaml b/packages/cli/test/configs/serve-legacy-2.21.5.yaml new file mode 100644 index 0000000000..fd2fa71ebf --- /dev/null +++ b/packages/cli/test/configs/serve-legacy-2.21.5.yaml @@ -0,0 +1,36 @@ +# Verbatim shape of a v2.21.5-era config (scenarios/test_codegen at the +# v2.21.5 tag, trimmed): `networks:`/`rpc_config:` keys that the current +# strict HumanConfig deserializers reject. `envio serve` must still read it. +name: test_codegen +description: Gravatar for Ethereum +rollback_on_reorg: true +save_full_history: false +field_selection: + transaction_fields: + - transactionIndex + - hash +contracts: + - name: Noop + handler: ./src/EventHandlers.bs.js + events: + - event: "EmptyEvent()" +networks: + - id: 1337 + rpc_config: + url: http://localhost:8545 + initial_block_interval: 10000 + backoff_multiplicative: 0.8 + acceleration_additive: 2000 + interval_ceiling: 10000 + backoff_millis: 5000 + query_timeout_millis: 20000 + start_block: 1 + contracts: + - name: Gravatar + abi_file_path: abis/gravatar-abi.json + address: "0x2B2f78c5BF6D9C12Ee1225D5F374aa91204580c3" + handler: ./src/EventHandlers.bs.js + events: + - event: "NewGravatar" + - event: "UpdatedGravatar" +raw_events: true diff --git a/packages/e2e-tests/bench-report.md b/packages/e2e-tests/bench-report.md new file mode 100644 index 0000000000..3fff3c4ba0 --- /dev/null +++ b/packages/e2e-tests/bench-report.md @@ -0,0 +1,612 @@ +# Differential benchmark — Hasura (recorded baseline) vs envio serve + +Baseline recorded 2026-07-03T16:32:35.282Z. 588 cases; per-case budget 1500ms, 3-30 iterations, warmup 2; case concurrency 1; sweep 413s. + +## Resources (envio serve, this sweep) + +| process | cpu seconds | peak rss (MB) | avg rss (MB) | +|---|---|---|---| +| envio serve | 7.4 | 255 | 231 | +| postgres | 376.0 | 712 | 499 | + +## Resources (hasura, at baseline recording time) + +| process | cpu seconds | peak rss (MB) | avg rss (MB) | +|---|---|---|---| +| hasura | 39.8 | 735 | 313 | +| postgres | 374.2 | 800 | 540 | + +## Per case + +| case | hasura p50 (ms, baseline) | envio p50 (ms) | envio p90 | speedup (p50) | samples | +|---|---|---|---|---|---| +| agg-aliases | 2.8 | 2.4 | 2.7 | x1.14 | 30 | +| agg-count-basic | 1.7 | 0.9 | 1.1 | x1.81 | 30 | +| agg-count-column | 1.9 | 1.1 | 1.5 | x1.66 | 30 | +| agg-count-distinct | 14.1 | 13.0 | 13.3 | x1.09 | 30 | +| agg-count-distinct-false | 16.5 | 15.2 | 16.6 | x1.09 | 30 | +| agg-count-with-where | 2.0 | 2.0 | 2.3 | x0.99 | 30 | +| agg-empty-set | 1.6 | 0.5 | 0.7 | x3.03 | 30 | +| agg-min-max-int | 2.1 | 1.3 | 1.6 | x1.62 | 30 | +| agg-min-max-numeric | 1.5 | 0.5 | 0.7 | x2.99 | 30 | +| agg-min-max-string | 1.4 | 0.6 | 0.7 | x2.55 | 30 | +| agg-min-max-timestamp | 1.6 | 0.4 | 0.5 | x3.51 | 30 | +| agg-nested-array-relationship | 268.9 | 265.4 | 270.4 | x1.01 | 6 | +| agg-nested-public-role-denied | 0.9 | 0.3 | 0.4 | x2.89 | 30 | +| agg-nested-with-args | 389.7 | 347.2 | 351.4 | x1.12 | 5 | +| agg-nodes | 1.5 | 0.4 | 0.5 | x3.65 | 30 | +| agg-nodes-only | 1.4 | 0.5 | 0.7 | x2.61 | 30 | +| agg-public-role-denied | 0.8 | 0.3 | 0.4 | x2.89 | 30 | +| agg-stddev-variance | 1.6 | 0.5 | 0.6 | x3.29 | 30 | +| agg-sum-avg-int-float | 1.8 | 0.6 | 2.5 | x2.92 | 30 | +| agg-sum-avg-numeric | 17.9 | 16.8 | 17.1 | x1.06 | 30 | +| agg-typename | 1.8 | 0.9 | 1.1 | x1.94 | 30 | +| agg-with-distinct-on | 212.1 | 193.4 | 200.2 | x1.10 | 8 | +| agg-with-limit-offset | 1.5 | 0.7 | 0.7 | x2.24 | 30 | +| am-agg-variables-where | 1.6 | 0.8 | 1.1 | x1.89 | 30 | +| am-chainmeta-float4-matrix | 1.6 | 0.7 | 1.0 | x2.21 | 30 | +| am-count-distinct-no-columns | 1.8 | 0.9 | 1.1 | x1.99 | 30 | +| am-count-distinct-no-nulls | 16.4 | 15.4 | 16.3 | x1.06 | 30 | +| am-count-distinct-with-nulls | 4.9 | 4.0 | 4.1 | x1.21 | 30 | +| am-count-multi-columns | 2.8 | 1.9 | 2.2 | x1.46 | 30 | +| am-count-multi-columns-distinct | 861.9 | 834.9 | 844.3 | x1.03 | 3 | +| am-empty-count-variants | 1.5 | 0.6 | 0.8 | x2.38 | 30 | +| am-empty-minmax-mixed-types | 1.7 | 0.6 | 0.7 | x2.98 | 30 | +| am-empty-numeric-all-operators | 2.0 | 0.5 | 0.7 | x3.62 | 30 | +| am-empty-with-nodes | 1.6 | 0.6 | 0.8 | x2.69 | 30 | +| am-error-avg-timestamp | 1.1 | 0.5 | 0.6 | x2.28 | 30 | +| am-error-count-distinct-wrong-type | 0.9 | 0.4 | 0.6 | x2.34 | 30 | +| am-error-count-unknown-column | 0.9 | 0.5 | 0.8 | x1.69 | 30 | +| am-error-min-bool | 1.0 | 0.4 | 1.3 | x2.33 | 30 | +| am-error-sum-jsonb | 0.9 | 0.4 | 0.7 | x2.10 | 30 | +| am-error-sum-text-column | 0.9 | 0.5 | 0.6 | x2.01 | 30 | +| am-error-variance-enum | 1.0 | 0.5 | 0.8 | x2.05 | 30 | +| am-float8-avg-nan | 1.5 | 0.4 | 0.5 | x3.61 | 30 | +| am-float8-minmax-infinity | 1.6 | 0.5 | 0.6 | x3.46 | 30 | +| am-float8-sum-infinity-nan | 1.5 | 0.5 | 0.7 | x3.05 | 30 | +| am-meta-float4-matrix | 1.8 | 0.9 | 1.4 | x2.00 | 30 | +| am-meta-int-sum-nullable | 1.6 | 0.8 | 1.0 | x1.91 | 30 | +| am-meta-minmax-timestamptz | 2.0 | 0.9 | 1.2 | x2.15 | 30 | +| am-minmax-enum | 1.3 | 0.5 | 0.8 | x2.42 | 30 | +| am-minmax-text-columns | 1.4 | 0.5 | 0.6 | x2.74 | 30 | +| am-minmax-text-unicode-empty | 1.4 | 0.4 | 0.5 | x3.30 | 30 | +| am-minmax-timestamptz | 1.5 | 0.5 | 0.9 | x2.90 | 30 | +| am-minmax-user-mixed | 3.5 | 2.4 | 2.5 | x1.47 | 30 | +| am-nested-agg-empty-owner | 1.8 | 0.7 | 1.0 | x2.59 | 30 | +| am-nested-agg-where-order-nodes | 1057.1 | 1060.4 | 1070.9 | x1.00 | 4 | +| am-nested-count-distinct | 162.6 | 159.7 | 161.7 | x1.02 | 10 | +| am-nested-full-combo | 556.3 | 506.5 | 507.1 | x1.10 | 3 | +| am-raw-bigint-avg-vs-int-avg | 10.1 | 9.1 | 9.5 | x1.11 | 30 | +| am-raw-bigint-minmax | 18.6 | 16.2 | 16.7 | x1.15 | 30 | +| am-raw-bigint-stddev-variance | 22.1 | 20.7 | 36.6 | x1.07 | 30 | +| am-raw-bigint-sum | 13.6 | 12.5 | 12.9 | x1.09 | 30 | +| am-raw-count-distinct-text-and-pair | 211.7 | 207.7 | 215.3 | x1.02 | 8 | +| am-raw-int-sum-overflows-int32 | 17.1 | 15.4 | 18.9 | x1.11 | 30 | +| am-root-distinct-on-aggregate | 183.7 | 182.6 | 185.3 | x1.01 | 9 | +| am-scalars-bigdecimal-full-matrix | 1.6 | 0.6 | 0.9 | x2.65 | 30 | +| am-scalars-bigint-full-matrix | 1.9 | 0.6 | 0.7 | x3.10 | 30 | +| am-scalars-float8-full-matrix | 1.8 | 0.6 | 0.9 | x2.96 | 30 | +| am-scalars-int-full-matrix | 1.6 | 0.6 | 0.7 | x2.95 | 30 | +| am-scalars-optint-null-handling | 1.7 | 0.5 | 0.6 | x3.58 | 30 | +| am-sim-int-full-matrix | 2.1 | 0.5 | 0.6 | x4.36 | 30 | +| am-single-row-stddev-null | 1.8 | 0.6 | 0.7 | x3.09 | 30 | +| am-token-numeric-full-matrix | 36.6 | 31.9 | 33.0 | x1.15 | 30 | +| am-user-avg-precision | 2.1 | 1.4 | 1.6 | x1.54 | 30 | +| am-user-int-full-matrix | 2.7 | 1.6 | 1.8 | x1.68 | 30 | +| basic-63-char-table | 1.5 | 0.7 | 1.0 | x2.20 | 30 | +| basic-admin-role | 24.4 | 16.7 | 18.0 | x1.46 | 30 | +| basic-alias-two-roots-same-table | 2.0 | 1.1 | 3.3 | x1.85 | 30 | +| basic-aliases | 1.7 | 0.8 | 1.0 | x2.11 | 30 | +| basic-by-pk-hit | 1.7 | 0.9 | 1.0 | x2.04 | 30 | +| basic-by-pk-miss | 1.5 | 0.8 | 1.1 | x1.75 | 30 | +| basic-by-pk-special-chars | 1.6 | 0.9 | 1.1 | x1.87 | 30 | +| basic-empty-table | 1.6 | 0.7 | 0.8 | x2.24 | 30 | +| basic-fragment-spread | 1.7 | 0.7 | 0.9 | x2.34 | 30 | +| basic-inline-fragment | 1.6 | 0.8 | 1.1 | x1.91 | 30 | +| basic-multiple-root-fields | 19.6 | 13.2 | 13.8 | x1.49 | 30 | +| basic-named-operation | 1.7 | 0.9 | 1.0 | x1.89 | 30 | +| basic-nested-fragments | 1.5 | 0.8 | 0.9 | x2.03 | 30 | +| basic-operation-name-selection | 1.6 | 0.9 | 1.2 | x1.85 | 30 | +| basic-restricted-field-name | 1.7 | 0.7 | 1.1 | x2.53 | 30 | +| basic-same-field-twice | 1.7 | 0.9 | 1.0 | x1.91 | 30 | +| basic-select-all-users | 47.0 | 31.8 | 35.4 | x1.48 | 30 | +| basic-skip-include | 1.8 | 0.9 | 1.1 | x1.98 | 30 | +| basic-skip-include-false | 1.7 | 0.8 | 0.9 | x2.07 | 30 | +| basic-typename-by-pk | 1.5 | 0.8 | 1.0 | x1.94 | 30 | +| basic-typename-root | 1.6 | 0.8 | 1.0 | x1.93 | 30 | +| basic-variables-default-value | 1.6 | 0.7 | 0.9 | x2.21 | 30 | +| basic-variables-null-optional | 13.1 | 8.7 | 11.4 | x1.51 | 30 | +| basic-variables-string | 1.6 | 0.7 | 0.9 | x2.23 | 30 | +| distinct-on-basic | 223.9 | 203.3 | 212.5 | x1.10 | 8 | +| distinct-on-enum-column | 5.7 | 4.8 | 4.9 | x1.18 | 30 | +| distinct-on-list | 1.5 | 0.7 | 0.8 | x2.22 | 30 | +| distinct-on-multiple-columns | 1.7 | 0.7 | 0.9 | x2.44 | 30 | +| distinct-on-with-limit | 6.5 | 5.5 | 6.6 | x1.18 | 30 | +| em-arg-distinct-on-unknown-column | 0.8 | 0.4 | 0.4 | x1.92 | 30 | +| em-arg-limit-as-list | 0.7 | 0.4 | 0.5 | x1.58 | 30 | +| em-arg-limit-as-object | 0.7 | 0.3 | 0.4 | x2.47 | 30 | +| em-arg-order-by-as-enum-literal | 0.7 | 0.2 | 0.6 | x2.84 | 30 | +| em-arg-order-by-as-string | 0.7 | 0.3 | 0.4 | x2.76 | 30 | +| em-arg-where-as-list | 0.7 | 0.3 | 0.3 | x2.61 | 30 | +| em-arg-where-as-string | 0.6 | 0.3 | 0.3 | x2.55 | 30 | +| em-body-lone-surrogate-in-query | 0.4 | 0.3 | 0.3 | x1.39 | 30 | +| em-by-pk-extra-unknown-arg | 0.7 | 0.2 | 0.3 | x2.99 | 30 | +| em-by-pk-id-null-literal | 0.8 | 0.2 | 0.3 | x3.27 | 30 | +| em-comments-only-query | 0.5 | 0.3 | 0.4 | x2.08 | 30 | +| em-deep-nesting-40-levels | 5.3 | 1.3 | 32.0 | x4.09 | 30 | +| em-directive-skip-on-query-operation | 0.7 | 0.3 | 0.4 | x2.86 | 30 | +| em-duplicate-argument-name | 0.5 | 0.4 | 0.5 | x1.35 | 30 | +| em-duplicate-key-in-input-object | 0.6 | 0.2 | 0.4 | x2.62 | 30 | +| em-duplicate-variable-definition | 0.7 | 0.3 | 0.4 | x2.87 | 30 | +| em-empty-selection-braces-field | 0.6 | 0.3 | 0.4 | x2.41 | 30 | +| em-empty-selection-braces-root | 0.6 | 0.3 | 0.4 | x2.31 | 30 | +| em-float-literal-overflow | 0.7 | 0.2 | 0.3 | x2.98 | 30 | +| em-fragment-on-enum-type | 1.4 | 0.5 | 0.5 | x2.90 | 30 | +| em-fragment-on-scalar-type | 1.4 | 0.5 | 0.7 | x2.76 | 30 | +| em-inline-fragment-unknown-type | 1.4 | 0.5 | 0.6 | x2.56 | 30 | +| em-inline-fragment-wrong-type | 1.4 | 0.5 | 0.7 | x2.53 | 30 | +| em-int-literal-overflow-int32 | 0.6 | 0.3 | 0.4 | x2.15 | 30 | +| em-int-literal-overflow-int64 | 0.7 | 0.3 | 0.4 | x2.50 | 30 | +| em-null-literal-limit | 1.4 | 0.5 | 0.8 | x2.72 | 30 | +| em-null-literal-where | 1.3 | 0.5 | 0.7 | x2.44 | 30 | +| em-opname-empty-string | 0.5 | 0.3 | 0.4 | x2.01 | 30 | +| em-string-bad-unicode-escape | 0.5 | 0.2 | 0.3 | x2.07 | 30 | +| em-string-lone-surrogate-escape | 0.5 | 0.2 | 0.3 | x2.08 | 30 | +| em-string-unknown-escape | 0.5 | 0.3 | 0.4 | x1.73 | 30 | +| em-subscription-multiple-root-fields | 0.8 | 0.3 | 0.4 | x2.72 | 30 | +| em-unknown-arg-aggregate-count | 0.8 | 0.3 | 0.3 | x2.91 | 30 | +| em-unknown-arg-on-scalar-column | 0.7 | 0.2 | 0.3 | x2.90 | 30 | +| em-unknown-field-aggregate-body | 0.8 | 0.2 | 0.3 | x3.35 | 30 | +| em-unknown-field-aggregate-wrapper | 0.7 | 0.3 | 0.5 | x2.62 | 30 | +| em-unknown-field-array-rel | 0.8 | 0.3 | 0.3 | x3.20 | 30 | +| em-unknown-field-object-rel | 0.7 | 0.3 | 0.3 | x2.76 | 30 | +| em-unknown-field-root-typo | 0.6 | 0.3 | 0.4 | x2.14 | 30 | +| em-unknown-operation-type-keyword | 0.7 | 0.2 | 0.3 | x3.31 | 30 | +| em-var-string-decl-used-as-int | 0.7 | 0.2 | 0.3 | x2.91 | 30 | +| em-var-wrong-name-used | 0.6 | 0.2 | 0.3 | x2.63 | 30 | +| em-whitespace-only-query | 0.6 | 0.2 | 0.3 | x2.56 | 30 | +| error-admin-secret-wrong | 0.4 | 0.3 | 0.4 | x1.47 | 30 | +| error-aggregate-public-not-exposed | 0.6 | 0.3 | 0.3 | x2.53 | 30 | +| error-by-pk-missing-arg | 0.7 | 0.3 | 0.3 | x2.87 | 30 | +| error-by-pk-wrong-arg-type | 0.7 | 0.3 | 0.6 | x2.20 | 30 | +| error-directive-unknown | 0.7 | 0.3 | 0.4 | x2.69 | 30 | +| error-distinct-on-without-matching-order | 0.7 | 0.3 | 0.4 | x2.42 | 30 | +| error-duplicate-operation-names | 1.2 | 0.5 | 0.6 | x2.33 | 30 | +| error-empty-query | 0.6 | 0.3 | 0.3 | x1.98 | 30 | +| error-enum-as-string-order-by | 0.7 | 0.3 | 0.5 | x2.43 | 30 | +| error-eq-null-literal | 0.8 | 0.3 | 0.4 | x2.59 | 30 | +| error-float-for-int-filter | 0.7 | 0.3 | 0.4 | x2.45 | 30 | +| error-fragment-cycle | 0.7 | 0.3 | 0.5 | x2.29 | 30 | +| error-fragment-undefined | 0.6 | 0.2 | 0.3 | x3.02 | 30 | +| error-fragment-unknown-type | 1.2 | 0.5 | 0.6 | x2.41 | 30 | +| error-fragment-unused | 1.2 | 0.5 | 0.7 | x2.25 | 30 | +| error-int-overflow-filter | 0.8 | 0.4 | 1.5 | x1.77 | 30 | +| error-invalid-enum-value | 1.3 | 0.6 | 0.8 | x2.09 | 30 | +| error-jsonb-path-invalid | 0.7 | 0.3 | 0.3 | x2.80 | 30 | +| error-like-on-int-column | 0.7 | 0.3 | 0.3 | x2.64 | 30 | +| error-limit-string | 0.7 | 0.3 | 0.5 | x2.07 | 30 | +| error-missing-required-variable | 0.6 | 0.3 | 0.5 | x2.46 | 30 | +| error-multiple-anonymous-operations | 0.6 | 0.3 | 0.5 | x1.74 | 30 | +| error-multiple-ops-no-operation-name | 0.6 | 0.3 | 0.4 | x2.04 | 30 | +| error-mutation-public | 0.6 | 0.3 | 0.5 | x2.04 | 30 | +| error-negative-limit | 0.7 | 0.3 | 0.4 | x2.41 | 30 | +| error-negative-offset | 1.3 | 0.6 | 0.9 | x2.01 | 30 | +| error-no-selection-set | 0.8 | 0.3 | 0.4 | x2.53 | 30 | +| error-null-for-required-variable | 0.6 | 0.3 | 0.4 | x2.28 | 30 | +| error-operation-name-not-found | 0.6 | 0.3 | 0.3 | x2.27 | 30 | +| error-scalar-with-selection | 0.7 | 0.3 | 0.3 | x2.82 | 30 | +| error-skip-missing-if | 0.7 | 0.3 | 0.3 | x2.78 | 30 | +| error-subscription-over-http | 0.7 | 0.3 | 0.4 | x2.36 | 30 | +| error-syntax | 0.6 | 0.3 | 0.4 | x2.24 | 30 | +| error-undeclared-variable-used | 0.7 | 0.3 | 0.4 | x2.62 | 30 | +| error-unknown-argument | 0.7 | 0.3 | 0.4 | x2.62 | 30 | +| error-unknown-column | 0.8 | 0.3 | 0.4 | x2.56 | 30 | +| error-unknown-op-in-bool-exp | 0.7 | 0.3 | 0.4 | x2.24 | 30 | +| error-unknown-root-field | 0.7 | 0.3 | 0.4 | x2.23 | 30 | +| error-unknown-variable-type | 12.5 | 8.7 | 9.4 | x1.43 | 30 | +| error-unused-variable | 0.6 | 0.3 | 0.4 | x2.18 | 30 | +| error-variable-wrong-type | 0.7 | 0.3 | 0.3 | x2.47 | 30 | +| error-where-wrong-type | 1.2 | 0.7 | 0.8 | x1.80 | 30 | +| internal-chain-metadata-no-by-pk | 1.5 | 0.7 | 1.0 | x2.02 | 30 | +| internal-chain-metadata-view | 1.5 | 0.5 | 0.7 | x2.80 | 30 | +| internal-meta-aggregate-admin | 1.4 | 0.6 | 0.9 | x2.35 | 30 | +| internal-meta-float4-precision | 1.6 | 0.5 | 0.7 | x2.83 | 30 | +| internal-meta-view | 1.6 | 0.6 | 0.7 | x2.79 | 30 | +| internal-meta-where-ready | 1.4 | 0.5 | 0.8 | x3.04 | 30 | +| internal-no-relationships-on-internal-tables | 1.8 | 0.9 | 1.2 | x1.92 | 30 | +| internal-raw-events-bigint-filter | 224.3 | 173.9 | 179.4 | x1.29 | 9 | +| internal-raw-events-by-pk | 1.5 | 0.7 | 1.0 | x2.34 | 30 | +| internal-raw-events-by-pk-miss | 1.3 | 0.6 | 0.7 | x2.27 | 30 | +| internal-raw-events-full | 2000.0 | 1410.2 | 1608.9 | x1.42 | 3 | +| internal-raw-events-jsonb-filter | 521.4 | 357.2 | 366.7 | x1.46 | 5 | +| internal-raw-events-jsonb-path | 45.3 | 47.0 | 50.6 | x0.96 | 30 | +| introspection-admin-query-root | 3.9 | 1.1 | 1.3 | x3.75 | 30 | +| introspection-admin-subscription-root | 3.8 | 1.0 | 1.2 | x3.91 | 30 | +| introspection-aggregate-types-admin | 1.4 | 0.4 | 0.8 | x3.45 | 30 | +| introspection-aggregate-types-hidden-public | 0.8 | 0.2 | 0.3 | x3.58 | 30 | +| introspection-deprecated-flag | 1.2 | 0.3 | 0.5 | x3.94 | 30 | +| introspection-descriptions | 0.8 | 0.3 | 0.4 | x3.03 | 30 | +| introspection-descriptions-bool-exp-and-order-by | 1.2 | 0.4 | 0.4 | x3.36 | 30 | +| introspection-descriptions-stream-cursor-value-input | 0.8 | 0.4 | 0.5 | x2.17 | 30 | +| introspection-full-public | 15.5 | 3.3 | 3.6 | x4.74 | 30 | +| introspection-mixed-with-data | 1.6 | 0.6 | 0.7 | x2.53 | 30 | +| introspection-stream-cursor-types | 1.4 | 0.3 | 0.4 | x4.84 | 30 | +| introspection-type-bool-exp | 1.2 | 0.4 | 0.5 | x3.03 | 30 | +| introspection-type-comparison-exp | 1.3 | 0.4 | 0.7 | x3.00 | 30 | +| introspection-type-entity | 1.2 | 0.3 | 0.6 | x3.55 | 30 | +| introspection-type-missing | 0.8 | 0.3 | 0.4 | x2.90 | 30 | +| introspection-type-order-by-enum | 0.9 | 0.3 | 0.4 | x2.56 | 30 | +| introspection-type-pg-enum-scalar | 0.8 | 0.3 | 0.4 | x2.65 | 30 | +| introspection-type-select-column | 0.9 | 0.4 | 0.5 | x2.54 | 30 | +| introspection-typename-meta | 0.7 | 0.3 | 0.4 | x2.35 | 30 | +| introspection-typename-on-typed-queries | 0.9 | 0.2 | 0.3 | x3.69 | 30 | +| limit-basic | 1.5 | 0.8 | 3.2 | x1.84 | 30 | +| limit-larger-than-rows | 1.4 | 0.6 | 0.8 | x2.26 | 30 | +| limit-offset-combo | 1.4 | 0.6 | 0.8 | x2.21 | 30 | +| limit-zero | 1.4 | 0.7 | 0.9 | x1.94 | 30 | +| offset-basic | 1.5 | 0.7 | 0.8 | x2.21 | 30 | +| offset-beyond-rows | 1.4 | 0.6 | 0.8 | x2.46 | 30 | +| om-distinct-extra-order-keys | 224.4 | 199.5 | 208.1 | x1.13 | 8 | +| om-distinct-multi-prefix-swapped | 1.6 | 0.8 | 0.9 | x2.13 | 30 | +| om-distinct-same-column-twice | 165.7 | 155.0 | 169.4 | x1.07 | 10 | +| om-error-distinct-not-first-in-order | 1.0 | 0.6 | 0.9 | x1.79 | 30 | +| om-error-distinct-unknown-column | 0.9 | 0.4 | 0.5 | x2.58 | 30 | +| om-error-order-array-rel-column | 0.9 | 0.5 | 0.6 | x1.76 | 30 | +| om-error-order-duplicate-key-in-object | 0.9 | 0.4 | 0.6 | x2.03 | 30 | +| om-error-order-unknown-column | 0.9 | 0.5 | 0.7 | x1.93 | 30 | +| om-introspect-token-aggregate-order-by | 1.3 | 0.5 | 0.8 | x2.57 | 30 | +| om-introspect-user-order-by | 1.1 | 0.5 | 0.7 | x2.35 | 30 | +| om-order-array-rel-aggregate-count-desc | 50.7 | 48.2 | 53.8 | x1.05 | 30 | +| om-order-array-rel-aggregate-max | 253.5 | 264.9 | 271.0 | x0.96 | 6 | +| om-order-bigint-raw-events-asc | 296.0 | 222.9 | 226.9 | x1.33 | 7 | +| om-order-bigint-raw-events-desc | 282.0 | 226.9 | 234.1 | x1.24 | 7 | +| om-order-bool-desc | 1.6 | 0.6 | 0.8 | x2.51 | 30 | +| om-order-directions-opt-bigint | 3.7 | 1.2 | 1.4 | x2.99 | 30 | +| om-order-directions-opt-enum | 3.7 | 1.3 | 1.5 | x2.85 | 30 | +| om-order-directions-opt-float | 4.0 | 1.3 | 1.5 | x3.02 | 30 | +| om-order-directions-opt-int | 3.7 | 1.3 | 1.5 | x2.91 | 30 | +| om-order-directions-opt-text | 141.9 | 107.7 | 110.1 | x1.32 | 14 | +| om-order-directions-opt-timestamp | 3.8 | 1.3 | 1.5 | x3.02 | 30 | +| om-order-enum-desc | 14.2 | 10.7 | 12.2 | x1.33 | 30 | +| om-order-float-special-desc | 1.6 | 0.7 | 3.3 | x2.32 | 30 | +| om-order-int-asc | 22.8 | 16.8 | 18.2 | x1.36 | 30 | +| om-order-int-desc | 21.5 | 15.7 | 17.6 | x1.38 | 30 | +| om-order-jsonb-asc | 1.6 | 0.7 | 3.0 | x2.15 | 30 | +| om-order-jsonb-desc-raw-events | 573.6 | 491.7 | 497.0 | x1.17 | 4 | +| om-order-mixed-list-with-multikey-object | 1.6 | 0.6 | 0.9 | x2.89 | 30 | +| om-order-multi-conflicting | 1.5 | 0.7 | 1.0 | x1.99 | 30 | +| om-order-multi-conflicting-flipped | 1.5 | 0.8 | 1.1 | x1.99 | 30 | +| om-order-multi-list-respects-order | 1.6 | 0.5 | 0.7 | x3.17 | 30 | +| om-order-numeric-bigdecimal-desc | 1.5 | 0.7 | 0.8 | x2.34 | 30 | +| om-order-numeric-bigint-asc | 1.6 | 0.7 | 1.3 | x2.15 | 30 | +| om-order-object-keys-blocknumber-first | 1.5 | 0.5 | 0.6 | x2.90 | 30 | +| om-order-object-keys-logindex-first | 1.5 | 0.6 | 0.6 | x2.59 | 30 | +| om-order-object-rel-nested-aggregate | 35650.7 | 35883.4 | 36109.1 | x0.99 | 3 | +| om-order-object-rel-owner-id | 673.1 | 622.3 | 689.3 | x1.08 | 3 | +| om-order-object-rel-two-levels | 1026.5 | 434.6 | 435.2 | x2.36 | 4 | +| om-order-optfloat-nan-asc | 1.6 | 0.7 | 0.8 | x2.40 | 30 | +| om-order-optfloat-nan-desc-nulls-last | 1.5 | 0.6 | 0.7 | x2.32 | 30 | +| om-order-same-column-twice-list | 1.5 | 0.6 | 0.9 | x2.38 | 30 | +| om-order-text-asc | 1.4 | 0.7 | 0.9 | x2.02 | 30 | +| om-order-timestamp-desc | 1.7 | 0.6 | 0.9 | x2.62 | 30 | +| order-asc | 438.4 | 298.0 | 300.9 | x1.47 | 6 | +| order-by-bool | 1.5 | 0.8 | 1.0 | x1.90 | 30 | +| order-by-enum-column | 13.7 | 10.3 | 10.9 | x1.32 | 30 | +| order-by-float-with-special | 1.6 | 0.8 | 0.9 | x1.93 | 30 | +| order-by-numeric | 454.5 | 330.9 | 345.0 | x1.37 | 5 | +| order-by-object-relationship-column | 22.8 | 21.8 | 22.4 | x1.05 | 30 | +| order-by-relationship-nested | 728.9 | 676.2 | 742.5 | x1.08 | 3 | +| order-by-timestamp | 1.7 | 0.8 | 1.4 | x2.08 | 30 | +| order-default-nulls-asc | 24.8 | 17.1 | 17.8 | x1.45 | 30 | +| order-default-nulls-desc | 24.8 | 17.0 | 17.6 | x1.46 | 30 | +| order-desc | 428.0 | 292.0 | 303.2 | x1.47 | 6 | +| order-desc-nulls-first | 25.2 | 17.1 | 17.7 | x1.47 | 30 | +| order-desc-nulls-last | 24.7 | 17.2 | 17.6 | x1.44 | 30 | +| order-multi-key-list | 1.6 | 0.7 | 0.8 | x2.23 | 30 | +| order-multi-key-single-object | 1.6 | 0.7 | 0.8 | x2.27 | 30 | +| order-nulls-first | 25.2 | 17.5 | 19.0 | x1.44 | 30 | +| order-nulls-last | 25.5 | 17.3 | 17.7 | x1.48 | 30 | +| rel-abcd-chain | 1.7 | 1.0 | 1.3 | x1.66 | 30 | +| rel-aliases-multiple-same-relationship | 2.1 | 1.1 | 1.4 | x1.86 | 30 | +| rel-array-basic | 668.5 | 596.1 | 636.4 | x1.12 | 3 | +| rel-array-distinct-on | 292.0 | 282.8 | 293.2 | x1.03 | 6 | +| rel-array-empty | 1.7 | 0.7 | 0.9 | x2.63 | 30 | +| rel-array-nested-args | 366.6 | 369.1 | 385.9 | x0.99 | 5 | +| rel-array-nested-offset | 39.8 | 39.1 | 42.4 | x1.02 | 30 | +| rel-circular-nesting | 1.7 | 0.9 | 1.2 | x2.02 | 30 | +| rel-deep-nesting | 1.8 | 0.9 | 1.1 | x2.06 | 30 | +| rel-derived-from-id-typed-key | 1.5 | 0.7 | 0.9 | x2.02 | 30 | +| rel-fragment-on-relationship | 2.3 | 1.3 | 1.5 | x1.74 | 30 | +| rel-object-basic | 32.7 | 25.2 | 26.4 | x1.30 | 30 | +| rel-object-dangling | 1.6 | 0.7 | 0.9 | x2.43 | 30 | +| rel-object-nullable-fk | 40.2 | 31.8 | 33.6 | x1.26 | 30 | +| rel-order-parent-by-child-aggregate-count | 51.6 | 46.4 | 47.6 | x1.11 | 30 | +| rel-order-parent-by-child-aggregate-max | 11.7 | 10.2 | 10.5 | x1.14 | 30 | +| rel-typename-in-nested | 1.5 | 0.8 | 1.0 | x1.73 | 30 | +| rel-where-on-parent-and-child | 20.9 | 19.8 | 21.5 | x1.06 | 30 | +| rm-agg-order-count-asc-empty-first | 11.2 | 9.9 | 10.1 | x1.14 | 30 | +| rm-agg-order-max-nulls-first | 11.4 | 10.1 | 11.0 | x1.13 | 30 | +| rm-agg-order-min-asc-nulls-first | 255.3 | 257.1 | 266.3 | x0.99 | 6 | +| rm-agg-order-sum-desc-nulls-last | 252.5 | 247.1 | 252.4 | x1.02 | 7 | +| rm-alias-conflict-rel-vs-column | 0.7 | 0.3 | 0.4 | x2.49 | 30 | +| rm-alias-swap-column-and-rel | 1.8 | 0.6 | 0.7 | x3.10 | 30 | +| rm-alias-user-gravatar-shadow | 1.8 | 0.7 | 0.9 | x2.61 | 30 | +| rm-child-all-args-collection-tokens | 202.5 | 196.1 | 205.1 | x1.03 | 8 | +| rm-child-all-args-user-tokens | 468.7 | 461.2 | 463.9 | x1.02 | 4 | +| rm-child-window-beyond-rows | 2.1 | 0.9 | 1.1 | x2.28 | 30 | +| rm-cross-and-inside-rel | 2.4 | 1.3 | 1.8 | x1.77 | 30 | +| rm-cross-and-parent-child | 2.7 | 2.3 | 2.5 | x1.19 | 30 | +| rm-cross-not-inside-rel | 88.3 | 21.1 | 22.2 | x4.18 | 30 | +| rm-cross-or-three-branches | 440.2 | 406.6 | 457.5 | x1.08 | 4 | +| rm-cross-or-two-rel-paths | 19.2 | 17.6 | 18.1 | x1.09 | 30 | +| rm-dangling-a-b | 1.5 | 0.4 | 0.7 | x3.47 | 30 | +| rm-dangling-b-c-all-rows | 1.6 | 0.5 | 0.7 | x3.10 | 30 | +| rm-dangling-d-via-rel-vs-column | 2.0 | 0.7 | 0.9 | x2.88 | 30 | +| rm-dangling-gravatar-owner | 1.7 | 0.5 | 0.8 | x3.10 | 30 | +| rm-dangling-token-collection | 1.7 | 0.7 | 0.8 | x2.52 | 30 | +| rm-dangling-token-owner | 1.6 | 0.6 | 0.8 | x2.91 | 30 | +| rm-dangling-user-gravatar | 1.6 | 0.5 | 0.7 | x2.90 | 30 | +| rm-deep-self-nesting-depth7 | 2.7 | 1.0 | 1.6 | x2.81 | 30 | +| rm-deep-where-self-referential | 1.7 | 0.7 | 1.5 | x2.41 | 30 | +| rm-exists-b-a-pair | 2.3 | 0.7 | 0.9 | x3.53 | 30 | +| rm-exists-bare-vs-predicate | 2.8 | 1.2 | 1.5 | x2.25 | 30 | +| rm-exists-c-d-pair | 2.0 | 0.7 | 0.8 | x2.99 | 30 | +| rm-exists-collection-tokens-pair | 2.9 | 1.2 | 1.4 | x2.48 | 30 | +| rm-exists-user-tokens-pair | 65.4 | 38.9 | 40.3 | x1.68 | 30 | +| rm-multihop-a-b-a-siblings | 1.8 | 0.6 | 0.7 | x3.02 | 30 | +| rm-multihop-a-b-c-d | 1.9 | 0.7 | 0.7 | x2.80 | 30 | +| rm-multihop-b-both-directions | 1.8 | 0.7 | 1.1 | x2.55 | 30 | +| rm-multihop-c-both-directions | 1.9 | 0.7 | 0.8 | x2.72 | 30 | +| rm-multihop-d-plain-column-filter | 1.8 | 0.7 | 0.9 | x2.79 | 30 | +| rm-object-exists-a-b-pair | 2.3 | 0.7 | 0.8 | x3.49 | 30 | +| rm-object-exists-gravatar-pair | 25.6 | 19.2 | 20.6 | x1.33 | 30 | +| rm-object-exists-vs-fk-not-null | 20.0 | 14.7 | 15.5 | x1.36 | 30 | +| rm-object-not-exists-b-c | 1.8 | 0.5 | 0.6 | x3.60 | 30 | +| rm-object-not-exists-gravatar-owner | 4.2 | 2.6 | 2.8 | x1.63 | 30 | +| rm-object-not-exists-token-collection | 52.5 | 21.4 | 22.0 | x2.45 | 30 | +| rm-object-not-exists-token-owner | 162.6 | 24.4 | 25.4 | x6.66 | 30 | +| rm-order-object-rel-dangling-nulls-first | 687.9 | 566.7 | 571.9 | x1.21 | 3 | +| rm-same-table-b-self-join | 1.8 | 0.7 | 0.9 | x2.77 | 30 | +| rm-same-table-token-and-sibling | 142.0 | 111.7 | 118.0 | x1.27 | 14 | +| rm-same-table-two-paths | 57.1 | 50.1 | 51.5 | x1.14 | 30 | +| scalars-all-non-array-full | 2.3 | 0.8 | 0.9 | x2.95 | 30 | +| scalars-all-types-full | 2.4 | 0.8 | 0.9 | x2.96 | 30 | +| scalars-bigdecimal-trailing-zeros | 1.5 | 0.7 | 0.9 | x2.17 | 30 | +| scalars-empty-arrays | 1.6 | 0.5 | 0.8 | x3.10 | 30 | +| scalars-float-special-values | 1.7 | 0.6 | 0.8 | x2.66 | 30 | +| scalars-jsonb-contained-in | 1.6 | 0.7 | 0.9 | x2.19 | 30 | +| scalars-jsonb-contains | 1.6 | 0.6 | 0.7 | x2.58 | 30 | +| scalars-jsonb-has-key | 1.6 | 0.5 | 0.8 | x2.90 | 30 | +| scalars-jsonb-has-keys-all | 1.5 | 0.7 | 4.7 | x2.18 | 30 | +| scalars-jsonb-has-keys-any | 1.6 | 0.6 | 0.8 | x2.64 | 30 | +| scalars-jsonb-path-arg | 1.5 | 0.6 | 0.7 | x2.67 | 30 | +| scalars-jsonb-path-index | 1.6 | 0.5 | 0.7 | x3.19 | 30 | +| scalars-jsonb-path-missing | 1.5 | 0.6 | 0.9 | x2.34 | 30 | +| scalars-jsonb-variants | 1.6 | 0.5 | 0.8 | x3.01 | 30 | +| scalars-numeric-array-precision | 1.5 | 0.5 | 0.7 | x2.92 | 30 | +| scalars-numeric-precision-monsters | 2.0 | 0.7 | 0.8 | x2.92 | 30 | +| scalars-string-arrays-escaping | 1.5 | 0.5 | 0.7 | x2.71 | 30 | +| scalars-timestamp-precision | 1.4 | 0.6 | 0.9 | x2.30 | 30 | +| scalars-unicode-strings | 1.6 | 0.6 | 0.8 | x2.79 | 30 | +| scalars-where-on-array-column-eq | 1.4 | 0.6 | 0.7 | x2.40 | 30 | +| ss-arrays-alltypes-string-vs-number | 1.8 | 0.6 | 0.7 | x3.01 | 30 | +| ss-arrays-numeric-precision-string-vs-number | 1.9 | 0.6 | 0.7 | x3.18 | 30 | +| ss-bypk-special-chars-full | 1.5 | 0.6 | 0.7 | x2.57 | 30 | +| ss-bypk-special-chars-variable | 1.5 | 0.6 | 0.7 | x2.61 | 30 | +| ss-field-order-interleaved | 1.5 | 0.6 | 0.8 | x2.58 | 30 | +| ss-field-order-reverse-schema | 1.9 | 0.7 | 0.8 | x2.69 | 30 | +| ss-json-alias-three-paths | 1.6 | 0.7 | 1.1 | x2.18 | 30 | +| ss-json-path-dollar-root | 1.4 | 0.6 | 0.9 | x2.20 | 30 | +| ss-json-path-empty-string-error | 0.9 | 0.3 | 0.5 | x2.66 | 30 | +| ss-json-path-key | 1.5 | 0.6 | 0.8 | x2.52 | 30 | +| ss-json-path-missing-nested | 1.6 | 0.6 | 0.8 | x2.59 | 30 | +| ss-json-path-nested-index | 1.5 | 0.5 | 0.7 | x2.95 | 30 | +| ss-json-path-no-dollar-prefix | 1.4 | 0.7 | 1.1 | x1.94 | 30 | +| ss-json-path-on-json-null | 1.5 | 0.6 | 0.6 | x2.72 | 30 | +| ss-json-path-on-scalar-value | 1.5 | 0.7 | 0.9 | x2.22 | 30 | +| ss-json-path-root-index | 1.5 | 0.6 | 0.9 | x2.46 | 30 | +| ss-json-path-unicode-key | 1.4 | 0.7 | 0.9 | x2.06 | 30 | +| ss-json-path-variable | 1.6 | 0.6 | 0.8 | x2.43 | 30 | +| ss-row-alltypes-all-1 | 1.9 | 0.8 | 0.9 | x2.50 | 30 | +| ss-row-alltypes-all-array-edge | 2.2 | 0.6 | 0.8 | x3.63 | 30 | +| ss-row-alltypes-all-empty-arrays | 1.8 | 0.5 | 0.6 | x3.41 | 30 | +| ss-row-alltypes-all-json-bool | 1.9 | 0.8 | 0.9 | x2.57 | 30 | +| ss-row-alltypes-all-json-null | 1.9 | 0.6 | 0.7 | x2.93 | 30 | +| ss-row-alltypes-all-json-number | 2.0 | 0.7 | 0.8 | x2.99 | 30 | +| ss-row-alltypes-all-json-string | 2.0 | 0.7 | 0.9 | x2.86 | 30 | +| ss-row-alltypes-all-json-unicode | 1.9 | 0.7 | 0.8 | x2.83 | 30 | +| ss-row-bigdecimal-bd-1 | 1.3 | 0.6 | 0.8 | x2.36 | 30 | +| ss-row-bigdecimal-bd-2 | 1.4 | 0.4 | 0.6 | x3.10 | 30 | +| ss-row-bigdecimal-bd-3 | 1.4 | 0.5 | 0.8 | x2.94 | 30 | +| ss-row-bigdecimal-bd-4 | 1.3 | 0.4 | 0.8 | x2.95 | 30 | +| ss-row-bigdecimal-bd-5 | 1.4 | 0.5 | 0.8 | x2.57 | 30 | +| ss-row-nonarray-scalar-1 | 2.1 | 0.7 | 2.2 | x2.81 | 30 | +| ss-row-nonarray-scalar-empty | 1.7 | 0.7 | 0.8 | x2.56 | 30 | +| ss-row-nonarray-scalar-extremes | 1.9 | 0.7 | 0.9 | x2.67 | 30 | +| ss-row-nonarray-scalar-neg-inf | 1.9 | 0.7 | 0.8 | x2.85 | 30 | +| ss-row-nonarray-scalar-nulls | 1.9 | 0.5 | 0.6 | x3.85 | 30 | +| ss-row-nonarray-scalar-quotes | 1.8 | 0.7 | 0.9 | x2.72 | 30 | +| ss-row-nonarray-scalar-special-float | 1.9 | 0.7 | 0.9 | x2.89 | 30 | +| ss-row-nonarray-scalar-unicode | 2.0 | 0.7 | 0.8 | x3.03 | 30 | +| ss-row-precision-prec-1 | 1.7 | 0.6 | 0.8 | x2.75 | 30 | +| ss-row-precision-prec-2 | 1.6 | 0.6 | 0.7 | x2.85 | 30 | +| ss-row-precision-prec-nulls | 1.4 | 0.5 | 0.7 | x3.05 | 30 | +| ss-row-timestamp-ts-epoch | 1.3 | 0.6 | 0.7 | x2.28 | 30 | +| ss-row-timestamp-ts-future | 1.5 | 0.5 | 0.7 | x2.75 | 30 | +| ss-row-timestamp-ts-micro | 1.3 | 0.5 | 0.6 | x2.85 | 30 | +| ss-row-timestamp-ts-milli | 1.3 | 0.4 | 0.4 | x3.38 | 30 | +| ss-row-timestamp-ts-pre-epoch | 1.5 | 0.5 | 0.6 | x2.94 | 30 | +| ss-row-timestamp-ts-zoned | 1.4 | 0.4 | 0.5 | x3.16 | 30 | +| ss-typename-only-by-pk | 1.5 | 0.5 | 0.8 | x3.13 | 30 | +| ss-typename-only-list | 1.4 | 0.5 | 0.6 | x2.77 | 30 | +| variables-limit-offset-order | 1.5 | 0.7 | 0.8 | x2.32 | 30 | +| vr-admin-mutation-insert-unknown-table | 0.7 | 0.3 | 0.4 | x2.21 | 30 | +| vr-alias-duplicate-root-different-args | 2.5 | 0.9 | 1.0 | x2.81 | 30 | +| vr-default-bool-exp-used | 1.5 | 0.7 | 0.8 | x2.16 | 30 | +| vr-default-int-overridden | 1.4 | 0.6 | 0.8 | x2.22 | 30 | +| vr-default-null-override | 1.4 | 0.7 | 0.9 | x2.08 | 30 | +| vr-directive-include-fragment-spread | 1.4 | 0.6 | 0.8 | x2.31 | 30 | +| vr-directive-include-fragment-spread-false | 1.5 | 0.7 | 1.1 | x2.13 | 30 | +| vr-directive-skip-inline-fragment | 1.4 | 0.5 | 0.6 | x3.06 | 30 | +| vr-error-boolean-string-in-include-directive | 0.9 | 0.6 | 1.0 | x1.53 | 30 | +| vr-error-directive-include-on-operation | 0.7 | 0.3 | 0.4 | x2.52 | 30 | +| vr-error-enum-scalar-invalid-value | 1.5 | 0.7 | 0.8 | x2.12 | 30 | +| vr-error-extra-undeclared-variable | 0.7 | 0.3 | 0.3 | x2.45 | 30 | +| vr-error-id-type-variable | 0.7 | 0.3 | 0.4 | x2.18 | 30 | +| vr-error-int-var-float-json | 0.7 | 0.4 | 0.6 | x1.76 | 30 | +| vr-error-int-var-string-json | 0.7 | 0.3 | 0.4 | x2.20 | 30 | +| vr-error-numeric-var-bool | 0.7 | 0.3 | 0.5 | x2.30 | 30 | +| vr-error-opname-with-anonymous-op | 0.6 | 0.3 | 0.4 | x1.77 | 30 | +| vr-error-same-alias-conflicting-args | 0.7 | 0.3 | 0.4 | x2.26 | 30 | +| vr-error-string-list-int-element | 0.8 | 0.4 | 0.5 | x2.14 | 30 | +| vr-fragment-chain-deep | 328.9 | 315.9 | 336.1 | x1.04 | 5 | +| vr-opname-query-beside-mutation-public | 1.3 | 0.5 | 0.8 | x2.54 | 30 | +| vr-opname-selects-op-with-vars | 1.5 | 0.6 | 0.7 | x2.56 | 30 | +| vr-typename-aggregate-admin | 363.8 | 302.1 | 361.2 | x1.20 | 6 | +| vr-typename-nested-everywhere | 1561.0 | 1465.4 | 1538.4 | x1.07 | 3 | +| vr-var-bool-exp-token | 417.6 | 302.6 | 304.6 | x1.38 | 5 | +| vr-var-boolean-string-in-where-coerced | 1.8 | 0.9 | 1.2 | x2.08 | 30 | +| vr-var-enum-scalar-accounttype | 5.9 | 4.4 | 4.9 | x1.32 | 30 | +| vr-var-float8-number | 2.1 | 0.8 | 0.9 | x2.56 | 30 | +| vr-var-float8-string-coerced | 1.6 | 0.9 | 1.1 | x1.77 | 30 | +| vr-var-int-limit-offset | 1.9 | 0.9 | 1.1 | x2.18 | 30 | +| vr-var-jsonb-object-contains | 1.7 | 0.7 | 0.9 | x2.35 | 30 | +| vr-var-jsonb-unicode-contains | 1.5 | 0.8 | 1.0 | x1.84 | 30 | +| vr-var-missing-variables-object | 1.3 | 0.5 | 0.8 | x2.66 | 30 | +| vr-var-nested-relationship-args | 369.3 | 362.1 | 372.6 | x1.02 | 5 | +| vr-var-null-for-nullable-args | 1.4 | 0.6 | 0.9 | x2.15 | 30 | +| vr-var-numeric-as-number | 1.6 | 0.7 | 0.8 | x2.39 | 30 | +| vr-var-numeric-as-string | 1.6 | 0.8 | 1.0 | x2.14 | 30 | +| vr-var-numeric-decimal-number | 1.8 | 0.8 | 0.9 | x2.33 | 30 | +| vr-var-order-by-enum-in-object-default | 1.3 | 0.7 | 0.8 | x2.03 | 30 | +| vr-var-order-by-list | 1.5 | 0.7 | 0.8 | x2.11 | 30 | +| vr-var-select-column-distinct-on | 207.5 | 195.2 | 198.1 | x1.06 | 8 | +| vr-var-select-column-single-value-coercion | 134.5 | 130.1 | 134.4 | x1.03 | 12 | +| vr-var-string-list-in | 1.6 | 0.8 | 1.0 | x2.10 | 30 | +| vr-var-string-list-single-value-coercion | 1.5 | 0.6 | 0.8 | x2.41 | 30 | +| vr-var-string-where | 1.6 | 0.8 | 0.9 | x2.08 | 30 | +| vr-var-timestamptz-string | 1.5 | 0.7 | 1.3 | x2.08 | 30 | +| where-and-empty-list | 1.6 | 0.6 | 0.7 | x2.47 | 30 | +| where-and-explicit | 16.3 | 12.9 | 13.7 | x1.26 | 30 | +| where-and-implicit | 9.3 | 7.0 | 7.7 | x1.33 | 30 | +| where-array-relationship | 66.8 | 63.8 | 65.4 | x1.05 | 25 | +| where-bool-eq | 1.6 | 0.7 | 0.9 | x2.16 | 30 | +| where-empty-bool-exp | 1.7 | 0.7 | 1.0 | x2.41 | 30 | +| where-empty-string-eq | 1.5 | 0.7 | 0.8 | x2.24 | 30 | +| where-enum-eq | 5.7 | 4.5 | 4.6 | x1.27 | 30 | +| where-enum-in | 14.3 | 13.0 | 14.0 | x1.10 | 30 | +| where-enum-neq | 9.2 | 7.2 | 7.6 | x1.29 | 30 | +| where-float-eq | 1.5 | 0.7 | 1.0 | x2.28 | 30 | +| where-float-gt | 1.7 | 0.7 | 0.9 | x2.53 | 30 | +| where-ilike | 7.7 | 6.8 | 7.3 | x1.13 | 30 | +| where-int-comparisons | 4.5 | 3.0 | 3.1 | x1.50 | 30 | +| where-int-negative | 2.2 | 1.5 | 1.7 | x1.50 | 30 | +| where-iregex | 1.8 | 0.7 | 1.0 | x2.50 | 30 | +| where-is-null-false | 10.0 | 7.2 | 7.7 | x1.38 | 30 | +| where-is-null-true | 10.4 | 7.5 | 7.9 | x1.40 | 30 | +| where-like | 6.5 | 5.7 | 5.9 | x1.15 | 30 | +| where-like-escape-chars | 1.7 | 0.8 | 1.0 | x2.04 | 30 | +| where-multiple-ops-same-column | 1.9 | 0.9 | 1.2 | x2.07 | 30 | +| where-nested-and-or-not | 5.7 | 4.5 | 4.9 | x1.29 | 30 | +| where-nilike | 20.7 | 16.5 | 21.6 | x1.26 | 30 | +| where-niregex | 1.8 | 0.8 | 1.1 | x2.14 | 30 | +| where-nlike | 20.1 | 15.8 | 16.6 | x1.27 | 30 | +| where-not | 16.5 | 12.8 | 15.2 | x1.28 | 30 | +| where-nsimilar | 1.8 | 0.7 | 0.9 | x2.43 | 30 | +| where-numeric-eq-int-literal | 1.6 | 0.8 | 0.9 | x2.10 | 30 | +| where-numeric-eq-string-literal | 1.6 | 0.8 | 1.9 | x1.91 | 30 | +| where-numeric-gt-huge | 1.8 | 0.9 | 1.0 | x2.01 | 30 | +| where-numeric-in-mixed | 1.8 | 0.7 | 0.9 | x2.48 | 30 | +| where-numeric-negative | 1.8 | 0.9 | 1.1 | x1.97 | 30 | +| where-object-relationship | 6.6 | 5.6 | 5.9 | x1.19 | 30 | +| where-or | 1.7 | 0.8 | 1.0 | x2.28 | 30 | +| where-or-empty-list | 1.4 | 0.6 | 0.8 | x2.27 | 30 | +| where-regex | 1.9 | 0.8 | 0.9 | x2.39 | 30 | +| where-relationship-is-null-object | 11.2 | 8.6 | 9.7 | x1.30 | 30 | +| where-relationship-nested-two-levels | 24.8 | 24.7 | 26.4 | x1.00 | 30 | +| where-similar | 1.8 | 0.8 | 0.9 | x2.21 | 30 | +| where-string-eq | 1.7 | 0.8 | 0.9 | x2.02 | 30 | +| where-string-gt-lt | 1.7 | 0.9 | 1.0 | x2.04 | 30 | +| where-string-gte-lte | 1.6 | 0.9 | 1.1 | x1.80 | 30 | +| where-string-in | 1.6 | 0.8 | 0.9 | x1.97 | 30 | +| where-string-in-empty | 1.6 | 0.7 | 0.9 | x2.21 | 30 | +| where-string-neq | 1.6 | 0.7 | 0.9 | x2.21 | 30 | +| where-string-nin | 1.6 | 0.8 | 0.9 | x1.96 | 30 | +| where-timestamp-eq | 1.6 | 0.7 | 0.9 | x2.23 | 30 | +| where-timestamp-range | 1.7 | 0.7 | 0.9 | x2.30 | 30 | +| where-timestamp-zoned-literal | 1.6 | 0.7 | 0.8 | x2.21 | 30 | +| where-unicode-value | 1.5 | 0.7 | 0.9 | x2.07 | 30 | +| where-variables-bool-exp | 4.6 | 3.9 | 4.3 | x1.20 | 30 | +| where-variables-nested-exp | 2.9 | 2.1 | 2.2 | x1.37 | 30 | +| wm-array-contains-contained-in | 2.2 | 0.7 | 0.9 | x3.04 | 30 | +| wm-array-eq-neq | 2.1 | 0.8 | 1.1 | x2.74 | 30 | +| wm-array-gt-gte | 2.1 | 0.8 | 1.1 | x2.65 | 30 | +| wm-array-in-database-error | 1.5 | 0.6 | 0.9 | x2.46 | 30 | +| wm-array-is-null | 2.0 | 0.7 | 0.7 | x3.02 | 30 | +| wm-array-lt-lte | 2.0 | 0.7 | 0.9 | x2.72 | 30 | +| wm-bigint-eq-neq | 154.2 | 108.6 | 116.6 | x1.42 | 14 | +| wm-bigint-eq-unquoted-64bit-literal | 7.7 | 6.2 | 6.7 | x1.24 | 30 | +| wm-bigint-gt-gte | 348.8 | 288.2 | 295.1 | x1.21 | 6 | +| wm-bigint-in-nin-mixed-literals | 151.2 | 171.4 | 187.4 | x0.88 | 9 | +| wm-bigint-is-null | 149.7 | 114.6 | 119.8 | x1.31 | 13 | +| wm-bigint-lt-lte-int-literal | 13.5 | 12.2 | 12.9 | x1.11 | 30 | +| wm-bool-eq-neq | 1.8 | 0.8 | 1.0 | x2.17 | 30 | +| wm-bool-gt-gte | 1.8 | 0.8 | 1.1 | x2.17 | 30 | +| wm-bool-in-nin | 1.9 | 0.8 | 1.1 | x2.24 | 30 | +| wm-bool-is-null | 1.9 | 0.9 | 1.3 | x2.18 | 30 | +| wm-bool-lt-lte | 2.0 | 0.8 | 1.1 | x2.41 | 30 | +| wm-enum-eq-neq | 20.1 | 16.7 | 17.8 | x1.20 | 30 | +| wm-enum-gt-gte | 38.6 | 30.8 | 32.7 | x1.26 | 30 | +| wm-enum-in-nin | 12.9 | 12.5 | 18.6 | x1.04 | 30 | +| wm-enum-is-null | 2.1 | 0.8 | 0.9 | x2.71 | 30 | +| wm-enum-lt-lte-declaration-order | 11.7 | 8.9 | 9.3 | x1.31 | 30 | +| wm-float-eq-infinity-literal | 1.5 | 0.6 | 0.8 | x2.30 | 30 | +| wm-float-eq-nan | 1.4 | 0.6 | 0.7 | x2.45 | 30 | +| wm-float-eq-neq | 1.9 | 0.7 | 0.9 | x2.57 | 30 | +| wm-float-eq-zero-matches-neg-zero | 1.6 | 0.6 | 0.8 | x2.55 | 30 | +| wm-float-gt-gte-dbl-max | 2.0 | 0.8 | 1.0 | x2.51 | 30 | +| wm-float-in-nin | 2.0 | 0.8 | 1.2 | x2.49 | 30 | +| wm-float-is-null | 1.9 | 0.8 | 1.0 | x2.32 | 30 | +| wm-float-lt-lte | 1.9 | 0.8 | 1.0 | x2.38 | 30 | +| wm-in-duplicate-values | 1.7 | 0.6 | 0.8 | x3.00 | 30 | +| wm-in-single-value | 1.5 | 0.5 | 0.7 | x2.83 | 30 | +| wm-int-eq-int32-max | 1.9 | 1.3 | 1.4 | x1.53 | 30 | +| wm-int-eq-int32-min | 1.9 | 1.4 | 1.6 | x1.37 | 30 | +| wm-int-eq-neq | 1.9 | 0.8 | 1.1 | x2.37 | 30 | +| wm-int-gt-gte | 1.9 | 0.8 | 1.0 | x2.45 | 30 | +| wm-int-in-nin | 15.6 | 16.1 | 16.7 | x0.97 | 30 | +| wm-int-is-null | 1.8 | 0.8 | 0.9 | x2.32 | 30 | +| wm-int-lt-lte | 3.9 | 2.4 | 2.5 | x1.61 | 30 | +| wm-is-null-false-with-like | 2.0 | 1.2 | 1.4 | x1.74 | 30 | +| wm-is-null-true-with-eq | 1.9 | 1.2 | 1.4 | x1.56 | 30 | +| wm-jsonb-cast-string-eq-scalar | 1.6 | 0.5 | 0.8 | x2.96 | 30 | +| wm-jsonb-cast-string-like | 1.5 | 0.5 | 0.8 | x2.79 | 30 | +| wm-jsonb-eq-empty-object | 1.5 | 0.6 | 0.8 | x2.60 | 30 | +| wm-jsonb-eq-nested-object | 1.4 | 0.6 | 0.8 | x2.22 | 30 | +| wm-jsonb-eq-object-literal | 26.2 | 23.7 | 25.1 | x1.11 | 30 | +| wm-numeric-eq-76-digits | 1.4 | 0.5 | 0.6 | x2.64 | 30 | +| wm-numeric-eq-neq-trailing-zero | 1.9 | 0.7 | 0.9 | x2.70 | 30 | +| wm-numeric-eq-tiny-fraction | 1.3 | 0.5 | 0.7 | x2.45 | 30 | +| wm-numeric-gt-gte | 1.9 | 0.8 | 1.0 | x2.49 | 30 | +| wm-numeric-in-nin | 246.4 | 313.3 | 315.2 | x0.79 | 5 | +| wm-numeric-is-null | 1.9 | 0.7 | 0.9 | x2.56 | 30 | +| wm-numeric-lt-lte | 1.8 | 0.7 | 0.9 | x2.40 | 30 | +| wm-text-eq-neq | 16.6 | 10.6 | 11.3 | x1.56 | 30 | +| wm-text-gt-gte | 3.6 | 2.5 | 2.9 | x1.42 | 30 | +| wm-text-ilike-nilike | 26.7 | 21.8 | 37.6 | x1.22 | 30 | +| wm-text-in-nin | 16.5 | 22.1 | 23.5 | x0.75 | 30 | +| wm-text-iregex-niregex | 21.3 | 16.4 | 17.6 | x1.29 | 30 | +| wm-text-is-null | 14.5 | 9.9 | 10.2 | x1.46 | 30 | +| wm-text-like-nlike | 26.8 | 21.5 | 22.2 | x1.24 | 30 | +| wm-text-lt-lte | 35.5 | 26.5 | 27.0 | x1.34 | 30 | +| wm-text-nin-empty | 1.3 | 0.6 | 0.8 | x2.23 | 30 | +| wm-text-regex-nregex | 28.3 | 23.6 | 24.7 | x1.20 | 30 | +| wm-text-similar-nsimilar | 20.9 | 16.6 | 17.2 | x1.26 | 30 | +| wm-ts-eq-neq | 2.0 | 1.0 | 1.2 | x2.00 | 30 | +| wm-ts-eq-normalized-offset | 1.4 | 0.7 | 1.0 | x2.00 | 30 | +| wm-ts-gt-gte | 1.9 | 1.0 | 1.2 | x1.87 | 30 | +| wm-ts-in-nin | 1.9 | 1.1 | 1.2 | x1.78 | 30 | +| wm-ts-is-null | 1.8 | 0.9 | 1.1 | x2.00 | 30 | +| wm-ts-lt-lte | 1.9 | 1.1 | 1.5 | x1.80 | 30 | + +Geometric-mean p50 speedup vs baseline: **x2.07**; cases >5% slower: **3**. diff --git a/packages/e2e-tests/fixtures/differential/bench-seed.sql b/packages/e2e-tests/fixtures/differential/bench-seed.sql new file mode 100644 index 0000000000..202bce7680 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/bench-seed.sql @@ -0,0 +1,59 @@ +-- Extra volume for benchmarks (applied on top of seed.sql): +-- 10k users, 50 collections, 200k tokens, 20k gravatars, 100k raw_events. +-- Deterministic (generate_series, no random()). + +INSERT INTO public."User" (id, address, gravatar_id, "updatesCountOnUserForTesting", "accountType") +SELECT + 'bench-user-' || i, + '0x' || lpad(to_hex(i), 40, '0'), + CASE WHEN i % 2 = 0 THEN 'bench-grav-' || (i / 2) ELSE NULL END, + i % 1000, + CASE WHEN i % 7 = 0 THEN 'ADMIN' ELSE 'USER' END::public.accounttype +FROM generate_series(1, 10000) i; + +INSERT INTO public."Gravatar" (id, owner_id, "displayName", "imageUrl", "updatesCount", size) +SELECT + 'bench-grav-' || i, + 'bench-user-' || (i * 2), + 'Bench Gravatar ' || i, + 'https://example.com/bench/' || i || '.png', + (i::numeric * 1000000000000000000), + (ARRAY['SMALL','MEDIUM','LARGE'])[1 + i % 3]::public.gravatarsize +FROM generate_series(1, 5000) i; + +INSERT INTO public."NftCollection" (id, "contractAddress", name, symbol, "maxSupply", "currentSupply") +SELECT + 'bench-coll-' || i, + '0x' || lpad(to_hex(i + 1000000), 40, 'c'), + 'Bench Collection ' || i, + 'B' || i, + (i::numeric) * 10000000000, + i * 100 +FROM generate_series(1, 50) i; + +INSERT INTO public."Token" (id, "tokenId", collection_id, owner_id) +SELECT + 'bench-tok-' || i, + (i::numeric * 31) % 1000000007, + 'bench-coll-' || (1 + i % 50), + 'bench-user-' || (1 + i % 10000) +FROM generate_series(1, 200000) i; + +INSERT INTO public.raw_events +(chain_id, event_id, event_name, contract_name, block_number, log_index, src_address, block_hash, block_timestamp, block_fields, transaction_fields, params) +SELECT + 1 + i % 3, + 4611686018427387904::bigint + i, + (ARRAY['Transfer','Approval','NewGravatar','UpdatedGravatar'])[1 + i % 4], + 'Gravatar', + 10000000 + i / 10, + i % 10, + '0x' || lpad(to_hex(i % 1000), 40, '0'), + '0x' || lpad(to_hex(i / 10), 64, 'b'), + 1600000000 + (i / 10) * 12, + json_build_object('number', 10000000 + i / 10)::jsonb, + json_build_object('hash', '0x' || lpad(to_hex(i), 64, 'a'), 'transactionIndex', i % 100)::jsonb, + json_build_object('from', '0x' || lpad(to_hex(i % 500), 40, '0'), 'to', '0x' || lpad(to_hex(i % 700), 40, '0'), 'value', (i::numeric * 1000000000)::text)::jsonb +FROM generate_series(1, 100000) i; + +ANALYZE public."User", public."Gravatar", public."NftCollection", public."Token", public.raw_events; diff --git a/packages/e2e-tests/fixtures/differential/hasura-baseline.json b/packages/e2e-tests/fixtures/differential/hasura-baseline.json new file mode 100644 index 0000000000..2ccc1b6578 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/hasura-baseline.json @@ -0,0 +1,4135 @@ +{ + "recordedAt": "2026-07-03T16:32:35.282Z", + "cases": { + "basic-by-pk-special-chars": { + "p50": 1.6184660000003532, + "p90": 1.8682530000000952, + "mean": 1.6535054666666382, + "min": 1.507372999999916, + "n": 30 + }, + "basic-typename-by-pk": { + "p50": 1.5008190000003196, + "p90": 1.705051999999796, + "mean": 1.5361341000000115, + "min": 1.3978790000001027, + "n": 30 + }, + "basic-by-pk-hit": { + "p50": 1.7414590000000771, + "p90": 2.0016489999998157, + "mean": 1.7595477666666814, + "min": 1.553385000000162, + "n": 30 + }, + "basic-by-pk-miss": { + "p50": 1.4706850000002305, + "p90": 1.6596239999998943, + "mean": 1.5434241333332996, + "min": 1.3748740000000907, + "n": 30 + }, + "basic-typename-root": { + "p50": 1.6123660000002928, + "p90": 1.7693010000002687, + "mean": 1.6881325000000136, + "min": 1.4770159999998214, + "n": 30 + }, + "basic-aliases": { + "p50": 1.6931719999997767, + "p90": 1.9259179999999105, + "mean": 2.4987836999999975, + "min": 1.513695000000098, + "n": 30 + }, + "basic-same-field-twice": { + "p50": 1.6504559999998492, + "p90": 1.8254669999996622, + "mean": 1.6672350999999557, + "min": 1.5413739999999052, + "n": 30 + }, + "basic-fragment-spread": { + "p50": 1.7486219999996138, + "p90": 1.9908259999997426, + "mean": 1.7715386000000004, + "min": 1.59695499999998, + "n": 30 + }, + "basic-alias-two-roots-same-table": { + "p50": 2.0468349999996462, + "p90": 2.5093839999999545, + "mean": 2.12180133333336, + "min": 1.728693999999905, + "n": 30 + }, + "basic-nested-fragments": { + "p50": 1.5440999999996166, + "p90": 1.8423179999999775, + "mean": 2.3576675999999375, + "min": 1.4365490000000136, + "n": 30 + }, + "basic-inline-fragment": { + "p50": 1.604820000000018, + "p90": 1.7390810000001693, + "mean": 1.6130988333333183, + "min": 1.4791199999999662, + "n": 30 + }, + "basic-variables-string": { + "p50": 1.586471999999958, + "p90": 1.8285829999999805, + "mean": 1.6881504333333093, + "min": 1.4986850000000231, + "n": 30 + }, + "basic-variables-default-value": { + "p50": 1.598428999999669, + "p90": 1.7346119999997427, + "mean": 1.6184630333332735, + "min": 1.490404000000126, + "n": 30 + }, + "basic-operation-name-selection": { + "p50": 1.6474319999997533, + "p90": 1.873000999999931, + "mean": 1.6578105333333042, + "min": 1.4006649999996625, + "n": 30 + }, + "basic-named-operation": { + "p50": 1.67770500000006, + "p90": 1.9177150000000438, + "mean": 1.7228974333333098, + "min": 1.4540039999997134, + "n": 30 + }, + "basic-skip-include": { + "p50": 1.7982179999999062, + "p90": 1.9884739999997691, + "mean": 1.8424954333333365, + "min": 1.6390259999998307, + "n": 30 + }, + "basic-skip-include-false": { + "p50": 1.7374449999997523, + "p90": 1.999561999999969, + "mean": 1.7674281333332602, + "min": 1.6109749999995984, + "n": 30 + }, + "basic-63-char-table": { + "p50": 1.547429999999622, + "p90": 1.716776000000209, + "mean": 1.5685180666666687, + "min": 1.4530930000000808, + "n": 30 + }, + "basic-empty-table": { + "p50": 1.6067830000001777, + "p90": 1.826086000000032, + "mean": 1.6200167666667766, + "min": 1.4154910000006566, + "n": 30 + }, + "basic-restricted-field-name": { + "p50": 1.6902120000004288, + "p90": 2.027535000000171, + "mean": 1.9112107666666514, + "min": 1.5033560000001671, + "n": 30 + }, + "where-string-eq": { + "p50": 1.7178270000003977, + "p90": 1.9985070000002452, + "mean": 1.755239966666674, + "min": 1.5890199999994365, + "n": 30 + }, + "where-string-neq": { + "p50": 1.635127999999895, + "p90": 1.731872000000294, + "mean": 1.6518235333333602, + "min": 1.575567000000774, + "n": 30 + }, + "where-string-in": { + "p50": 1.6397969999998168, + "p90": 1.8422039999995832, + "mean": 2.447178200000023, + "min": 1.4758819999997286, + "n": 30 + }, + "basic-multiple-root-fields": { + "p50": 19.614105999999992, + "p90": 21.606554999999844, + "mean": 20.481022499999973, + "min": 18.987491999999747, + "n": 30 + }, + "basic-select-all-users": { + "p50": 46.963254000000006, + "p90": 53.581400999999914, + "mean": 48.515943166666645, + "min": 43.37285299999985, + "n": 30 + }, + "where-string-in-empty": { + "p50": 1.5959929999999076, + "p90": 1.7738540000000285, + "mean": 1.611508466666631, + "min": 1.4494299999996656, + "n": 30 + }, + "basic-variables-null-optional": { + "p50": 13.13497499999994, + "p90": 13.878747000000203, + "mean": 13.70589359999999, + "min": 12.351886999999806, + "n": 30 + }, + "where-string-nin": { + "p50": 1.6071050000000469, + "p90": 1.7502159999994547, + "mean": 1.6531532666667468, + "min": 1.4352940000007948, + "n": 30 + }, + "where-string-gt-lt": { + "p50": 1.7416429999993852, + "p90": 2.176101999999446, + "mean": 1.8163263333332906, + "min": 1.544659999999567, + "n": 30 + }, + "where-string-gte-lte": { + "p50": 1.5708199999999124, + "p90": 2.0466459999997824, + "mean": 1.7043638999999833, + "min": 1.4143620000004375, + "n": 30 + }, + "where-like": { + "p50": 6.53788700000041, + "p90": 6.979256999999961, + "mean": 6.601426399999915, + "min": 6.253034999999727, + "n": 30 + }, + "where-similar": { + "p50": 1.7986760000003414, + "p90": 2.028303000000051, + "mean": 1.8134637333333254, + "min": 1.5816020000002027, + "n": 30 + }, + "where-nsimilar": { + "p50": 1.7717659999998432, + "p90": 2.290288000000146, + "mean": 2.0223389999999197, + "min": 1.5341869999992923, + "n": 30 + }, + "where-ilike": { + "p50": 7.705221000000165, + "p90": 8.587048999999752, + "mean": 7.887227166666465, + "min": 7.508098999999675, + "n": 30 + }, + "where-regex": { + "p50": 1.8790979999994306, + "p90": 2.123827999999776, + "mean": 1.9401555666666657, + "min": 1.570082999999613, + "n": 30 + }, + "basic-admin-role": { + "p50": 24.371586000000207, + "p90": 26.276280000000042, + "mean": 25.163781133333366, + "min": 23.048077000000376, + "n": 30 + }, + "where-iregex": { + "p50": 1.841511999999966, + "p90": 2.062159000000065, + "mean": 1.8525025333334573, + "min": 1.6411580000003596, + "n": 30 + }, + "where-niregex": { + "p50": 1.8037109999995664, + "p90": 1.9385039999997389, + "mean": 1.7758023333333464, + "min": 1.525354000000334, + "n": 30 + }, + "where-like-escape-chars": { + "p50": 1.655416999999943, + "p90": 2.1342819999999847, + "mean": 2.4954598666666548, + "min": 1.4027590000005148, + "n": 30 + }, + "where-int-negative": { + "p50": 2.191001999999571, + "p90": 2.3148909999999887, + "mean": 2.2022404333331, + "min": 2.0475059999989753, + "n": 30 + }, + "where-nlike": { + "p50": 20.08264700000018, + "p90": 22.142243999999664, + "mean": 20.778672133333323, + "min": 19.40480899999966, + "n": 30 + }, + "where-int-comparisons": { + "p50": 4.455803000000742, + "p90": 4.764578000000256, + "mean": 4.575260766666725, + "min": 4.277947999999014, + "n": 30 + }, + "where-numeric-eq-string-literal": { + "p50": 1.6219120000005205, + "p90": 3.4431769999991957, + "mean": 2.5699206666665, + "min": 1.3301860000010493, + "n": 30 + }, + "where-nilike": { + "p50": 20.748209000000315, + "p90": 30.562673999999788, + "mean": 22.19857743333332, + "min": 20.009562999999616, + "n": 30 + }, + "where-numeric-eq-int-literal": { + "p50": 1.6292620000003808, + "p90": 2.618916999999783, + "mean": 1.7804781333332358, + "min": 1.3980930000016087, + "n": 30 + }, + "where-numeric-in-mixed": { + "p50": 1.7839610000009998, + "p90": 1.97758900000008, + "mean": 1.7845508333334388, + "min": 1.597808000000441, + "n": 30 + }, + "where-numeric-gt-huge": { + "p50": 1.8147759999992559, + "p90": 2.097649999999703, + "mean": 1.8386382666667487, + "min": 1.6751309999999648, + "n": 30 + }, + "where-numeric-negative": { + "p50": 1.7729309999995166, + "p90": 1.9805150000011054, + "mean": 1.850498700000147, + "min": 1.650766000000658, + "n": 30 + }, + "where-is-null-true": { + "p50": 10.443987000000561, + "p90": 11.087166000000252, + "mean": 10.566613766666705, + "min": 9.82802300000003, + "n": 30 + }, + "where-is-null-false": { + "p50": 9.970116999998936, + "p90": 11.064218999999866, + "mean": 10.714522999999826, + "min": 9.424919000000955, + "n": 30 + }, + "where-float-eq": { + "p50": 1.5448859999996785, + "p90": 1.7181490000002668, + "mean": 1.5582446999998865, + "min": 1.3709629999993922, + "n": 30 + }, + "where-bool-eq": { + "p50": 1.583133000000089, + "p90": 1.676803000000291, + "mean": 1.5851650333333358, + "min": 1.3682879999996658, + "n": 30 + }, + "where-float-gt": { + "p50": 1.6688450000001467, + "p90": 1.9424799999997049, + "mean": 1.7506357333333653, + "min": 1.475722000001042, + "n": 30 + }, + "where-timestamp-eq": { + "p50": 1.6369939999985945, + "p90": 1.8285809999997582, + "mean": 1.6586217333334692, + "min": 1.4786189999995258, + "n": 30 + }, + "where-timestamp-zoned-literal": { + "p50": 1.6112919999995938, + "p90": 1.7660219999997935, + "mean": 1.5930140333332625, + "min": 1.4231239999990066, + "n": 30 + }, + "where-timestamp-range": { + "p50": 1.6957660000007309, + "p90": 2.0636089999989053, + "mean": 1.8733276333333682, + "min": 1.5214750000013737, + "n": 30 + }, + "where-enum-eq": { + "p50": 5.706560000000536, + "p90": 6.761336000001393, + "mean": 6.855488533333422, + "min": 5.339292000000569, + "n": 30 + }, + "where-or": { + "p50": 1.7154669999999896, + "p90": 2.025911000000633, + "mean": 1.739695800000239, + "min": 1.4827370000002702, + "n": 30 + }, + "where-enum-neq": { + "p50": 9.24355100000139, + "p90": 9.564125999999305, + "mean": 9.36146460000012, + "min": 8.905187000000296, + "n": 30 + }, + "where-nested-and-or-not": { + "p50": 5.737923000000592, + "p90": 6.179672999998729, + "mean": 5.896212533333467, + "min": 5.203623000001244, + "n": 30 + }, + "where-and-implicit": { + "p50": 9.338485999998738, + "p90": 9.866316999999981, + "mean": 10.179008133333081, + "min": 8.80873900000006, + "n": 30 + }, + "where-empty-bool-exp": { + "p50": 1.7329370000006747, + "p90": 1.954518000000462, + "mean": 1.7437728333332416, + "min": 1.5317350000004808, + "n": 30 + }, + "where-and-empty-list": { + "p50": 1.577714000000924, + "p90": 1.9959539999999834, + "mean": 2.427816733333384, + "min": 1.372201000000132, + "n": 30 + }, + "where-or-empty-list": { + "p50": 1.4433570000001055, + "p90": 1.5764149999995425, + "mean": 1.445130533333213, + "min": 1.250385000001188, + "n": 30 + }, + "where-enum-in": { + "p50": 14.3375130000004, + "p90": 15.149256000000605, + "mean": 14.818747533333408, + "min": 13.777115999999296, + "n": 30 + }, + "where-and-explicit": { + "p50": 16.287946000000375, + "p90": 19.728234000000157, + "mean": 17.07850906666651, + "min": 12.553705000000264, + "n": 30 + }, + "where-not": { + "p50": 16.46010000000024, + "p90": 25.760134999998627, + "mean": 18.0707204666669, + "min": 12.708714999998847, + "n": 30 + }, + "where-multiple-ops-same-column": { + "p50": 1.8686520000010205, + "p90": 2.8865509999995993, + "mean": 2.0790827999999237, + "min": 1.744909999999436, + "n": 30 + }, + "where-object-relationship": { + "p50": 6.644453000000794, + "p90": 7.1462179999998625, + "mean": 6.7027882666666, + "min": 6.338940999999977, + "n": 30 + }, + "where-empty-string-eq": { + "p50": 1.501693999998679, + "p90": 1.6586680000000342, + "mean": 1.5092611000000034, + "min": 1.327729000000545, + "n": 30 + }, + "where-unicode-value": { + "p50": 1.4891660000012052, + "p90": 1.6983780000009574, + "mean": 1.5121765999998389, + "min": 1.3451310000000376, + "n": 30 + }, + "where-variables-bool-exp": { + "p50": 4.649649999999383, + "p90": 5.003856999999698, + "mean": 5.414230099999865, + "min": 4.447390999999698, + "n": 30 + }, + "where-variables-nested-exp": { + "p50": 2.871014999998806, + "p90": 3.1304589999999735, + "mean": 2.906707866666754, + "min": 2.7254379999994853, + "n": 30 + }, + "where-relationship-is-null-object": { + "p50": 11.176165000000765, + "p90": 12.100459000001138, + "mean": 12.014184966666836, + "min": 10.741878000000725, + "n": 30 + }, + "where-relationship-nested-two-levels": { + "p50": 24.78855400000066, + "p90": 26.891778999999588, + "mean": 25.981055966666585, + "min": 24.397710999999617, + "n": 30 + }, + "where-array-relationship": { + "p50": 66.81574200000068, + "p90": 72.16136600000027, + "mean": 65.36258045833347, + "min": 30.19559399999889, + "n": 24 + }, + "order-nulls-first": { + "p50": 25.167277000000468, + "p90": 37.42060800000036, + "mean": 26.95416976666614, + "min": 23.988422999998875, + "n": 30 + }, + "order-nulls-last": { + "p50": 25.491502000000764, + "p90": 26.5568740000017, + "mean": 25.727874900000096, + "min": 23.957815000001574, + "n": 30 + }, + "order-desc-nulls-last": { + "p50": 24.734975999999733, + "p90": 26.79386499999964, + "mean": 26.00233213333316, + "min": 23.648440000000846, + "n": 30 + }, + "order-desc-nulls-first": { + "p50": 25.196726000001945, + "p90": 35.6050019999966, + "mean": 26.716341866666212, + "min": 23.87857499999882, + "n": 30 + }, + "order-multi-key-single-object": { + "p50": 1.5907760000009148, + "p90": 1.751681000001554, + "mean": 1.602989000000404, + "min": 1.4505649999991874, + "n": 30 + }, + "order-multi-key-list": { + "p50": 1.5721620000003895, + "p90": 1.77045999999973, + "mean": 1.5953123333332768, + "min": 1.4273189999985334, + "n": 30 + }, + "order-default-nulls-desc": { + "p50": 24.811863999999332, + "p90": 26.454546000000846, + "mean": 25.694313133333587, + "min": 24.04688300000271, + "n": 30 + }, + "order-default-nulls-asc": { + "p50": 24.80401200000051, + "p90": 26.48175099999935, + "mean": 25.243128366666618, + "min": 23.661831000001257, + "n": 30 + }, + "order-by-bool": { + "p50": 1.537216000000626, + "p90": 1.798242000000755, + "mean": 1.5835315333336135, + "min": 1.4466219999994792, + "n": 30 + }, + "order-by-timestamp": { + "p50": 1.7489280000008876, + "p90": 1.8995919999979378, + "mean": 1.7336522333333657, + "min": 1.521286000002874, + "n": 30 + }, + "order-by-enum-column": { + "p50": 13.651178000000073, + "p90": 14.760804999998072, + "mean": 14.630188799999814, + "min": 12.935257000001002, + "n": 30 + }, + "order-asc": { + "p50": 438.3964539999979, + "p90": 467.01405299999897, + "mean": 438.61956550000014, + "min": 420.9056430000019, + "n": 4 + }, + "order-desc": { + "p50": 427.99191300000166, + "p90": 476.789638000002, + "mean": 435.7979869999999, + "min": 414.6789269999972, + "n": 4 + }, + "order-by-float-with-special": { + "p50": 1.5956619999997201, + "p90": 1.8452580000011949, + "mean": 1.6249233333335724, + "min": 1.4217620000017632, + "n": 30 + }, + "limit-zero": { + "p50": 1.4227140000002692, + "p90": 1.6855070000019623, + "mean": 1.6739284999996016, + "min": 1.2242699999987963, + "n": 30 + }, + "limit-basic": { + "p50": 1.4711949999982608, + "p90": 4.589241000001493, + "mean": 2.2500160333329404, + "min": 1.2306959999987157, + "n": 30 + }, + "limit-larger-than-rows": { + "p50": 1.4382169999953476, + "p90": 1.7035940000059782, + "mean": 1.4738528333342402, + "min": 1.3112269999983255, + "n": 30 + }, + "offset-basic": { + "p50": 1.450842999998713, + "p90": 1.8498250000047847, + "mean": 1.5939818000006198, + "min": 1.2250520000015968, + "n": 30 + }, + "offset-beyond-rows": { + "p50": 1.4390160000039032, + "p90": 1.6865600000019185, + "mean": 1.4855040333335636, + "min": 1.3732470000031753, + "n": 30 + }, + "limit-offset-combo": { + "p50": 1.3859020000018063, + "p90": 3.243823999997403, + "mean": 2.3422379333334296, + "min": 1.2292270000034478, + "n": 30 + }, + "distinct-on-list": { + "p50": 1.5374339999980293, + "p90": 1.7227039999997942, + "mean": 1.557496499999009, + "min": 1.418998000001011, + "n": 30 + }, + "distinct-on-multiple-columns": { + "p50": 1.7141019999980927, + "p90": 1.9508589999968535, + "mean": 1.7250025000003613, + "min": 1.475975000001199, + "n": 30 + }, + "order-by-object-relationship-column": { + "p50": 22.832770999997592, + "p90": 24.602403999997478, + "mean": 23.47560139999999, + "min": 21.924057000000175, + "n": 30 + }, + "variables-limit-offset-order": { + "p50": 1.5210759999972652, + "p90": 1.7696649999998044, + "mean": 1.6153875000006035, + "min": 1.2716229999932693, + "n": 30 + }, + "distinct-on-enum-column": { + "p50": 5.651914999994915, + "p90": 5.856873000004271, + "mean": 5.677495600000111, + "min": 5.480522999998357, + "n": 30 + }, + "rel-object-dangling": { + "p50": 1.592917000001762, + "p90": 2.35693899999751, + "mean": 2.4956124333327656, + "min": 1.327168999996502, + "n": 30 + }, + "distinct-on-with-limit": { + "p50": 6.501310999999987, + "p90": 6.941164000003482, + "mean": 7.375433700001062, + "min": 6.3008649999974295, + "n": 30 + }, + "order-by-numeric": { + "p50": 454.4845920000007, + "p90": 474.5966550000012, + "mean": 457.1186292500015, + "min": 448.9016670000019, + "n": 4 + }, + "distinct-on-basic": { + "p50": 223.90276400000585, + "p90": 242.20876200000203, + "mean": 224.66267228571607, + "min": 209.4357369999998, + "n": 7 + }, + "rel-object-basic": { + "p50": 32.73207099999854, + "p90": 34.2245630000034, + "mean": 33.47841166666622, + "min": 31.44692699999723, + "n": 30 + }, + "rel-array-empty": { + "p50": 1.722965999993903, + "p90": 2.121305000000575, + "mean": 1.868779266666388, + "min": 1.4168439999994007, + "n": 30 + }, + "rel-object-nullable-fk": { + "p50": 40.18373699999938, + "p90": 42.898191000000224, + "mean": 41.12002253333315, + "min": 39.275547000004735, + "n": 30 + }, + "rel-deep-nesting": { + "p50": 1.8392839999942225, + "p90": 2.167333999997936, + "mean": 1.8676462999998573, + "min": 1.5989090000002761, + "n": 30 + }, + "rel-circular-nesting": { + "p50": 1.7287480000013602, + "p90": 2.0925500000012107, + "mean": 1.8258957999998529, + "min": 1.5705330000055255, + "n": 30 + }, + "rel-abcd-chain": { + "p50": 1.7249599999995553, + "p90": 2.168697000000975, + "mean": 1.792551866666569, + "min": 1.5850110000028508, + "n": 30 + }, + "rel-derived-from-id-typed-key": { + "p50": 1.4898570000004838, + "p90": 1.7217640000017127, + "mean": 1.5211797666668039, + "min": 1.3475840000028256, + "n": 30 + }, + "rel-array-nested-offset": { + "p50": 39.79703100000188, + "p90": 41.257103999996616, + "mean": 40.760574600000595, + "min": 39.03745899999922, + "n": 30 + }, + "rel-aliases-multiple-same-relationship": { + "p50": 2.0851869999969495, + "p90": 2.3095790000006673, + "mean": 2.090584966666211, + "min": 1.9256919999970705, + "n": 30 + }, + "rel-fragment-on-relationship": { + "p50": 2.285615000000689, + "p90": 2.6622450000068056, + "mean": 2.3337697000002664, + "min": 2.090034000000742, + "n": 30 + }, + "rel-typename-in-nested": { + "p50": 1.4610309999989113, + "p90": 1.8096989999976358, + "mean": 1.5409155000010892, + "min": 1.267468000005465, + "n": 30 + }, + "rel-array-distinct-on": { + "p50": 292.04013600000326, + "p90": 305.10761099999945, + "mean": 293.49257133333475, + "min": 286.00873700000375, + "n": 6 + }, + "rel-array-nested-args": { + "p50": 366.6146499999959, + "p90": 388.17470100000355, + "mean": 372.4360965999993, + "min": 363.8828379999977, + "n": 5 + }, + "order-by-relationship-nested": { + "p50": 728.9240449999998, + "p90": 794.3957210000008, + "mean": 741.4130593333321, + "min": 700.9194119999956, + "n": 3 + }, + "scalars-all-non-array-full": { + "p50": 2.3415729999978794, + "p90": 2.8940549999970244, + "mean": 2.5947781333333597, + "min": 2.045037999996566, + "n": 30 + }, + "scalars-all-types-full": { + "p50": 2.3708800000022165, + "p90": 2.852980999996362, + "mean": 3.2874323999996706, + "min": 2.2006120000005467, + "n": 30 + }, + "rel-where-on-parent-and-child": { + "p50": 20.896162999997614, + "p90": 22.435044999998354, + "mean": 21.9010431, + "min": 20.395243999999366, + "n": 30 + }, + "rel-order-parent-by-child-aggregate-max": { + "p50": 11.656135000004724, + "p90": 12.09625099999539, + "mean": 12.542181133334088, + "min": 11.110539000001154, + "n": 30 + }, + "rel-order-parent-by-child-aggregate-count": { + "p50": 51.567278999995324, + "p90": 63.06403499999578, + "mean": 53.57261639285649, + "min": 49.24364600000263, + "n": 28 + }, + "scalars-float-special-values": { + "p50": 1.704846999993606, + "p90": 1.9224780000004102, + "mean": 1.71769406666596, + "min": 1.4658130000025267, + "n": 30 + }, + "scalars-numeric-precision-monsters": { + "p50": 1.9711070000048494, + "p90": 2.175046000003931, + "mean": 1.980693600000571, + "min": 1.7448379999987083, + "n": 30 + }, + "scalars-timestamp-precision": { + "p50": 1.4475670000028913, + "p90": 1.661710000000312, + "mean": 1.5223328999997952, + "min": 1.2962570000017877, + "n": 30 + }, + "scalars-bigdecimal-trailing-zeros": { + "p50": 1.461524999998801, + "p90": 1.6502590000018245, + "mean": 1.478562800000509, + "min": 1.3033419999992475, + "n": 30 + }, + "scalars-jsonb-variants": { + "p50": 1.588091000005079, + "p90": 1.807503000003635, + "mean": 1.6214349000001675, + "min": 1.4518180000013672, + "n": 30 + }, + "scalars-jsonb-path-arg": { + "p50": 1.5301679999975022, + "p90": 1.975125000004482, + "mean": 1.5820295999995626, + "min": 1.3900359999970533, + "n": 30 + }, + "scalars-jsonb-path-index": { + "p50": 1.5736199999955716, + "p90": 1.7672830000010435, + "mean": 1.5832254000003256, + "min": 1.3531890000012936, + "n": 30 + }, + "scalars-jsonb-path-missing": { + "p50": 1.5090500000005704, + "p90": 1.885604000002786, + "mean": 1.6265121999997063, + "min": 1.372947000003478, + "n": 30 + }, + "scalars-jsonb-contains": { + "p50": 1.591072000002896, + "p90": 1.7454779999970924, + "mean": 1.6836544333324128, + "min": 1.354764999996405, + "n": 30 + }, + "scalars-jsonb-contained-in": { + "p50": 1.6012229999978445, + "p90": 1.843250000005355, + "mean": 1.6485038666665788, + "min": 1.457196000003023, + "n": 30 + }, + "scalars-jsonb-has-key": { + "p50": 1.572718999996141, + "p90": 1.7661320000042906, + "mean": 1.587506599999809, + "min": 1.4215429999967455, + "n": 30 + }, + "scalars-jsonb-has-keys-any": { + "p50": 1.6012919999993755, + "p90": 1.930062999999791, + "mean": 1.7600729333336251, + "min": 1.4512920000051963, + "n": 30 + }, + "scalars-string-arrays-escaping": { + "p50": 1.4860499999995227, + "p90": 1.6494810000003781, + "mean": 1.5171248999999078, + "min": 1.3840029999992112, + "n": 30 + }, + "scalars-empty-arrays": { + "p50": 1.6123159999988275, + "p90": 1.8097380000035628, + "mean": 1.6423426000006052, + "min": 1.4182369999980438, + "n": 30 + }, + "scalars-jsonb-has-keys-all": { + "p50": 1.5399950000064564, + "p90": 2.1772150000033434, + "mean": 1.7961444333341205, + "min": 1.4139329999961774, + "n": 30 + }, + "scalars-numeric-array-precision": { + "p50": 1.549010000002454, + "p90": 1.847646000001987, + "mean": 1.597184233333246, + "min": 1.377042000000074, + "n": 30 + }, + "scalars-unicode-strings": { + "p50": 1.6250419999996666, + "p90": 1.807465999998385, + "mean": 2.5248952999992373, + "min": 1.4580579999965266, + "n": 30 + }, + "scalars-where-on-array-column-eq": { + "p50": 1.3908319999973173, + "p90": 1.483234999999695, + "mean": 1.4007736999997482, + "min": 1.2139349999997648, + "n": 30 + }, + "agg-count-basic": { + "p50": 1.6527530000021216, + "p90": 1.89423999999417, + "mean": 1.691244366666797, + "min": 1.4449030000032508, + "n": 30 + }, + "agg-count-with-where": { + "p50": 1.9932709999993676, + "p90": 2.2369890000045416, + "mean": 2.0159422333337718, + "min": 1.8574870000011288, + "n": 30 + }, + "agg-count-column": { + "p50": 1.8922719999973197, + "p90": 2.1387609999947017, + "mean": 2.00842613333225, + "min": 1.6914800000013201, + "n": 30 + }, + "agg-min-max-string": { + "p50": 1.4264970000003814, + "p90": 1.677823999998509, + "mean": 1.4591724333329088, + "min": 1.3044299999965006, + "n": 30 + }, + "agg-min-max-int": { + "p50": 2.0542650000061258, + "p90": 2.171011999998882, + "mean": 2.0805714333340197, + "min": 1.940722999999707, + "n": 30 + }, + "agg-min-max-numeric": { + "p50": 1.5484250000008615, + "p90": 1.7031370000040624, + "mean": 2.3752176666663822, + "min": 1.2203149999986636, + "n": 30 + }, + "agg-min-max-timestamp": { + "p50": 1.5582200000062585, + "p90": 1.7072450000050594, + "mean": 1.5454488000007889, + "min": 1.2796759999982896, + "n": 30 + }, + "agg-sum-avg-int-float": { + "p50": 1.8262049999975716, + "p90": 2.0828959999998915, + "mean": 1.7990521666659334, + "min": 1.4512770000001183, + "n": 30 + }, + "agg-stddev-variance": { + "p50": 1.6471820000006119, + "p90": 1.9318050000001676, + "mean": 1.6633761666673914, + "min": 1.3893779999998515, + "n": 30 + }, + "agg-empty-set": { + "p50": 1.6325639999995474, + "p90": 1.942551000000094, + "mean": 1.661645299999994, + "min": 1.4124809999993886, + "n": 30 + }, + "rel-array-basic": { + "p50": 668.5346449999997, + "p90": 729.1491949999981, + "mean": 688.2534249999977, + "min": 667.0764349999954, + "n": 3 + }, + "agg-nodes": { + "p50": 1.4528149999969173, + "p90": 1.5591529999946943, + "mean": 1.4476803666654936, + "min": 1.2970310000018799, + "n": 30 + }, + "agg-count-distinct": { + "p50": 14.096106999997573, + "p90": 16.047601999998733, + "mean": 15.026262199999959, + "min": 13.748300000006566, + "n": 30 + }, + "agg-nodes-only": { + "p50": 1.4283729999951902, + "p90": 1.554163000000699, + "mean": 1.440823399999499, + "min": 1.248424999997951, + "n": 30 + }, + "agg-with-limit-offset": { + "p50": 1.4625020000021323, + "p90": 1.947306000001845, + "mean": 2.392376333333474, + "min": 1.268817999996827, + "n": 30 + }, + "agg-aliases": { + "p50": 2.750298999992083, + "p90": 3.0557150000095135, + "mean": 2.7831756000004435, + "min": 2.553884000008111, + "n": 30 + }, + "agg-count-distinct-false": { + "p50": 16.500843999994686, + "p90": 17.68893499999831, + "mean": 16.845734833334184, + "min": 15.56588699999702, + "n": 30 + }, + "agg-public-role-denied": { + "p50": 0.791335000001709, + "p90": 0.9100580000085756, + "mean": 0.8111706666677492, + "min": 0.6450960000074701, + "n": 30 + }, + "agg-typename": { + "p50": 1.7870569999940926, + "p90": 1.9651730000041425, + "mean": 1.8078679666674968, + "min": 1.603820000003907, + "n": 30 + }, + "agg-nested-public-role-denied": { + "p50": 0.9010260000068229, + "p90": 1.2085819999920204, + "mean": 0.9826690333332712, + "min": 0.7643880000105128, + "n": 30 + }, + "agg-sum-avg-numeric": { + "p50": 17.87676199999987, + "p90": 18.209805999998935, + "mean": 18.67369926666603, + "min": 17.610351000002993, + "n": 30 + }, + "internal-meta-view": { + "p50": 1.563477999996394, + "p90": 1.7953140000026906, + "mean": 1.6040962666656318, + "min": 1.419580000001588, + "n": 30 + }, + "internal-meta-float4-precision": { + "p50": 1.5564899999881163, + "p90": 1.84661400000914, + "mean": 1.6751248333321807, + "min": 1.3324560000037309, + "n": 30 + }, + "internal-meta-where-ready": { + "p50": 1.4361009999993257, + "p90": 1.688034000006155, + "mean": 1.5164473333328108, + "min": 1.2645210000046063, + "n": 30 + }, + "internal-chain-metadata-view": { + "p50": 1.5294779999967432, + "p90": 1.789801000006264, + "mean": 1.557872100000289, + "min": 1.380615999994916, + "n": 30 + }, + "internal-raw-events-by-pk": { + "p50": 1.5328210000006948, + "p90": 1.7655570000060834, + "mean": 3.031675066666503, + "min": 1.379572999998345, + "n": 30 + }, + "internal-raw-events-by-pk-miss": { + "p50": 1.3424799999920651, + "p90": 1.5343870000069728, + "mean": 1.4390893999991627, + "min": 1.1782250000105705, + "n": 30 + }, + "agg-with-distinct-on": { + "p50": 212.1017839999986, + "p90": 247.3546040000001, + "mean": 215.53213937499913, + "min": 204.69477500000357, + "n": 8 + }, + "agg-nested-array-relationship": { + "p50": 268.89104000000225, + "p90": 323.66833999999653, + "mean": 276.5104086666688, + "min": 264.07779600000504, + "n": 6 + }, + "internal-no-relationships-on-internal-tables": { + "p50": 1.8196119999920484, + "p90": 2.3972329999960493, + "mean": 1.9185041000013976, + "min": 1.5843020000029355, + "n": 30 + }, + "internal-meta-aggregate-admin": { + "p50": 1.410831999994116, + "p90": 1.6690600000001723, + "mean": 1.5313973666663514, + "min": 1.2456009999878006, + "n": 30 + }, + "internal-raw-events-bigint-filter": { + "p50": 224.3391910000064, + "p90": 253.10426699998789, + "mean": 228.5566728571409, + "min": 221.55546299999696, + "n": 7 + }, + "internal-raw-events-jsonb-path": { + "p50": 45.33423700000276, + "p90": 61.291830999995, + "mean": 47.53589486666703, + "min": 43.44730800000252, + "n": 30 + }, + "error-unknown-root-field": { + "p50": 0.6702550000045449, + "p90": 0.8841739999916172, + "mean": 0.702278866667378, + "min": 0.6025490000029095, + "n": 30 + }, + "internal-chain-metadata-no-by-pk": { + "p50": 1.4979810000077123, + "p90": 1.7777599999972153, + "mean": 1.5698655666647634, + "min": 1.3256260000052862, + "n": 30 + }, + "error-unknown-column": { + "p50": 0.76745500000834, + "p90": 0.9337629999936325, + "mean": 0.78077166666626, + "min": 0.6341779999929713, + "n": 30 + }, + "agg-nested-with-args": { + "p50": 389.70527700000093, + "p90": 393.6412410000048, + "mean": 388.95960900000136, + "min": 384.92921000000206, + "n": 4 + }, + "error-unknown-argument": { + "p50": 0.7090309999912279, + "p90": 0.9625599999999395, + "mean": 1.7080137000002045, + "min": 0.6183710000041174, + "n": 30 + }, + "error-syntax": { + "p50": 0.6096110000071349, + "p90": 0.7049340000085067, + "mean": 0.6042032666674155, + "min": 0.5024859999975888, + "n": 30 + }, + "error-empty-query": { + "p50": 0.5579020000004675, + "p90": 0.81846600001154, + "mean": 0.588583000000411, + "min": 0.4839990000036778, + "n": 30 + }, + "error-no-selection-set": { + "p50": 0.7735479999973904, + "p90": 0.9361970000027213, + "mean": 0.8599338333335861, + "min": 0.6221999999979744, + "n": 30 + }, + "error-scalar-with-selection": { + "p50": 0.7469609999970999, + "p90": 0.9223879999917699, + "mean": 0.7713771333326197, + "min": 0.6239110000024084, + "n": 30 + }, + "error-by-pk-missing-arg": { + "p50": 0.7394880000065314, + "p90": 0.9584429999958957, + "mean": 0.7543991333324811, + "min": 0.6207750000030501, + "n": 30 + }, + "error-by-pk-wrong-arg-type": { + "p50": 0.7484820000099717, + "p90": 0.9579579999990528, + "mean": 0.8616587333327819, + "min": 0.6523220000090078, + "n": 30 + }, + "error-enum-as-string-order-by": { + "p50": 0.7369480000052135, + "p90": 0.8307119999954011, + "mean": 0.7346985333337216, + "min": 0.6268730000010692, + "n": 30 + }, + "error-limit-string": { + "p50": 0.7116370000003371, + "p90": 0.8685770000010962, + "mean": 0.7340984333330804, + "min": 0.620586999997613, + "n": 30 + }, + "error-invalid-enum-value": { + "p50": 1.333104999997886, + "p90": 1.4989619999978459, + "mean": 1.356449333333391, + "min": 1.1857740000123158, + "n": 30 + }, + "error-negative-limit": { + "p50": 0.687792000011541, + "p90": 0.79602700000396, + "mean": 0.7047673666665408, + "min": 0.577579999997397, + "n": 30 + }, + "error-unknown-op-in-bool-exp": { + "p50": 0.7195300000021234, + "p90": 0.8255289999942761, + "mean": 0.7389541000006526, + "min": 0.6489279999950668, + "n": 30 + }, + "error-eq-null-literal": { + "p50": 0.7523309999960475, + "p90": 0.8714970000000903, + "mean": 0.7662100333322693, + "min": 0.6379890000098385, + "n": 30 + }, + "error-negative-offset": { + "p50": 1.3021220000082394, + "p90": 1.6427879999973811, + "mean": 1.4085774000001645, + "min": 1.0889230000029784, + "n": 30 + }, + "error-int-overflow-filter": { + "p50": 0.7688729999936186, + "p90": 1.0746729999955278, + "mean": 0.8958085000005667, + "min": 0.6635800000076415, + "n": 30 + }, + "error-where-wrong-type": { + "p50": 1.173437000004924, + "p90": 1.2698810000001686, + "mean": 1.1779954999995728, + "min": 1.0894310000003316, + "n": 30 + }, + "error-float-for-int-filter": { + "p50": 0.7476429999951506, + "p90": 1.0125269999989541, + "mean": 1.861550700000953, + "min": 0.6264040000096429, + "n": 30 + }, + "error-missing-required-variable": { + "p50": 0.6341129999927944, + "p90": 0.7427279999974417, + "mean": 0.6276000666650361, + "min": 0.49262699999962933, + "n": 30 + }, + "error-null-for-required-variable": { + "p50": 0.6280429999897024, + "p90": 0.7429940000001807, + "mean": 0.6382949333346914, + "min": 0.503089000005275, + "n": 30 + }, + "error-variable-wrong-type": { + "p50": 0.7076779999915743, + "p90": 0.8577779999905033, + "mean": 0.7380848666667589, + "min": 0.5990770000062184, + "n": 30 + }, + "error-unused-variable": { + "p50": 0.6307700000033947, + "p90": 0.765067000000272, + "mean": 0.654517133331198, + "min": 0.508823999989545, + "n": 30 + }, + "error-undeclared-variable-used": { + "p50": 0.6637729999929434, + "p90": 0.9758920000022044, + "mean": 0.7831440666651663, + "min": 0.511847999994643, + "n": 30 + }, + "error-multiple-anonymous-operations": { + "p50": 0.6015730000071926, + "p90": 0.749110999997356, + "mean": 0.5995364333333176, + "min": 0.46644399999058805, + "n": 30 + }, + "error-operation-name-not-found": { + "p50": 0.6132260000013048, + "p90": 0.708874999996624, + "mean": 0.6083043333351573, + "min": 0.4668740000051912, + "n": 30 + }, + "error-multiple-ops-no-operation-name": { + "p50": 0.6073069999984, + "p90": 0.7760479999997187, + "mean": 0.612291166667031, + "min": 0.4273049999901559, + "n": 30 + }, + "error-fragment-undefined": { + "p50": 0.6467689999990398, + "p90": 0.764246999999159, + "mean": 0.6579258333333807, + "min": 0.5169800000003306, + "n": 30 + }, + "error-duplicate-operation-names": { + "p50": 1.2252669999870704, + "p90": 1.3941000000049826, + "mean": 1.3140686999991886, + "min": 1.1164589999971213, + "n": 30 + }, + "error-fragment-unknown-type": { + "p50": 1.155361000011908, + "p90": 1.320679000011296, + "mean": 1.175532166666623, + "min": 1.0459689999988768, + "n": 30 + }, + "error-fragment-cycle": { + "p50": 0.6788919999962673, + "p90": 0.7947470000071917, + "mean": 0.688424566668012, + "min": 0.6132959999958985, + "n": 30 + }, + "error-fragment-unused": { + "p50": 1.151322000005166, + "p90": 1.3463449999981094, + "mean": 1.1888716000001296, + "min": 1.0798389999981737, + "n": 30 + }, + "error-mutation-public": { + "p50": 0.6375689999986207, + "p90": 0.9275630000047386, + "mean": 0.749198566666261, + "min": 0.528269000002183, + "n": 30 + }, + "error-subscription-over-http": { + "p50": 0.6692230000044219, + "p90": 0.754572999998345, + "mean": 0.6865803000007873, + "min": 0.6184940000093775, + "n": 30 + }, + "error-distinct-on-without-matching-order": { + "p50": 0.667025000002468, + "p90": 0.7056569999986095, + "mean": 0.6580165666654163, + "min": 0.5868800000025658, + "n": 30 + }, + "error-aggregate-public-not-exposed": { + "p50": 0.6491839999944204, + "p90": 0.8050359999906505, + "mean": 0.6617367999982283, + "min": 0.5600609999964945, + "n": 30 + }, + "error-jsonb-path-invalid": { + "p50": 0.7486350000108359, + "p90": 0.8988860000099521, + "mean": 0.7677552666680033, + "min": 0.6225819999963278, + "n": 30 + }, + "error-like-on-int-column": { + "p50": 0.6906440000020666, + "p90": 0.8274130000063451, + "mean": 0.854795166667221, + "min": 0.5955170000088401, + "n": 30 + }, + "error-directive-unknown": { + "p50": 0.6739569999917876, + "p90": 0.8248060000041733, + "mean": 1.618761400000949, + "min": 0.5892230000026757, + "n": 30 + }, + "error-skip-missing-if": { + "p50": 0.7152539999951841, + "p90": 0.8422849999915343, + "mean": 0.7209695666645227, + "min": 0.5916569999972126, + "n": 30 + }, + "error-admin-secret-wrong": { + "p50": 0.44262000000162516, + "p90": 0.587746999997762, + "mean": 0.4476459000002554, + "min": 0.32873500000278, + "n": 30 + }, + "error-unknown-variable-type": { + "p50": 12.508837000001222, + "p90": 13.21102799999062, + "mean": 13.912774199999209, + "min": 11.95069899999362, + "n": 30 + }, + "introspection-admin-query-root": { + "p50": 3.9379710000066552, + "p90": 4.145802999992156, + "mean": 3.9554964666671975, + "min": 3.68008700000064, + "n": 30 + }, + "introspection-admin-subscription-root": { + "p50": 3.782697000002372, + "p90": 4.441403999997419, + "mean": 3.8902640666691393, + "min": 3.416144999995595, + "n": 30 + }, + "introspection-typename-meta": { + "p50": 0.7359850000066217, + "p90": 0.8134169999975711, + "mean": 0.7462145666659732, + "min": 0.6459729999914998, + "n": 30 + }, + "internal-raw-events-jsonb-filter": { + "p50": 521.4111459999986, + "p90": 523.4530189999932, + "mean": 487.47747024999626, + "min": 443.24836199999845, + "n": 4 + }, + "introspection-full-public": { + "p50": 15.5198240000027, + "p90": 24.22970599999826, + "mean": 17.589355333331817, + "min": 14.845158999989508, + "n": 30 + }, + "introspection-type-entity": { + "p50": 1.2135490000073332, + "p90": 1.3722669999988284, + "mean": 1.242902133334913, + "min": 1.1420510000025388, + "n": 30 + }, + "introspection-type-comparison-exp": { + "p50": 1.2923549999977695, + "p90": 1.8564189999888185, + "mean": 1.4423091666646846, + "min": 1.1111320000054548, + "n": 30 + }, + "introspection-type-bool-exp": { + "p50": 1.23920999999973, + "p90": 1.410370999990846, + "mean": 1.2625349666651648, + "min": 1.1446969999960857, + "n": 30 + }, + "introspection-type-order-by-enum": { + "p50": 0.8623950000037439, + "p90": 0.9793420000059996, + "mean": 0.8619462666674129, + "min": 0.7370089999894844, + "n": 30 + }, + "introspection-type-select-column": { + "p50": 0.8963470000016969, + "p90": 0.9925680000014836, + "mean": 0.8866763000017576, + "min": 0.7486540000099922, + "n": 30 + }, + "introspection-type-pg-enum-scalar": { + "p50": 0.8047229999938281, + "p90": 0.8956900000048336, + "mean": 0.8045954333336947, + "min": 0.7049879999976838, + "n": 30 + }, + "introspection-type-missing": { + "p50": 0.782349000000977, + "p90": 0.9110030000010738, + "mean": 0.7956161333335331, + "min": 0.679984999995213, + "n": 30 + }, + "introspection-aggregate-types-hidden-public": { + "p50": 0.7805309999966994, + "p90": 0.9302400000015041, + "mean": 0.807446166665856, + "min": 0.6808690000034403, + "n": 30 + }, + "introspection-typename-on-typed-queries": { + "p50": 0.8580280000023777, + "p90": 0.9701469999999972, + "mean": 0.8565991000000698, + "min": 0.7391269999934593, + "n": 30 + }, + "introspection-aggregate-types-admin": { + "p50": 1.3857799999968847, + "p90": 1.6459829999948852, + "mean": 1.5090549666657656, + "min": 1.2651480000058655, + "n": 30 + }, + "introspection-stream-cursor-types": { + "p50": 1.4133330000040587, + "p90": 1.5686289999866858, + "mean": 1.4312727333327833, + "min": 1.260095999998157, + "n": 30 + }, + "introspection-deprecated-flag": { + "p50": 1.2221350000036182, + "p90": 1.3527739999990445, + "mean": 1.2978212333337675, + "min": 1.0885319999943022, + "n": 30 + }, + "introspection-mixed-with-data": { + "p50": 1.563972999996622, + "p90": 1.7864989999943646, + "mean": 2.48119266666569, + "min": 1.3507390000013402, + "n": 30 + }, + "wm-text-gt-gte": { + "p50": 3.570879999999306, + "p90": 3.923196999996435, + "mean": 3.6263379999999112, + "min": 3.4059549999947194, + "n": 30 + }, + "wm-text-eq-neq": { + "p50": 16.561803000004147, + "p90": 18.57326100001228, + "mean": 17.174000600001698, + "min": 14.990880000012112, + "n": 30 + }, + "wm-text-in-nin": { + "p50": 16.517565000001923, + "p90": 17.419891999990796, + "mean": 17.429368266666035, + "min": 15.669926000002306, + "n": 30 + }, + "wm-text-is-null": { + "p50": 14.469785000008414, + "p90": 14.752867999995942, + "mean": 14.4272285666666, + "min": 13.656558000002406, + "n": 30 + }, + "wm-text-lt-lte": { + "p50": 35.54636700000265, + "p90": 37.12906999999541, + "mean": 35.522363999999655, + "min": 26.63197199998831, + "n": 30 + }, + "wm-text-like-nlike": { + "p50": 26.7862199999945, + "p90": 29.88497600000119, + "mean": 27.454721066667116, + "min": 25.635398999991594, + "n": 30 + }, + "wm-int-eq-neq": { + "p50": 1.8859170000068843, + "p90": 2.267686000006506, + "mean": 1.9350329000037163, + "min": 1.6218369999987772, + "n": 30 + }, + "wm-int-gt-gte": { + "p50": 1.886056000003009, + "p90": 2.2417849999910686, + "mean": 1.9335066666676235, + "min": 1.6448579999996582, + "n": 30 + }, + "wm-int-lt-lte": { + "p50": 3.9284679999982473, + "p90": 4.744655999995302, + "mean": 4.968494733333743, + "min": 3.439022999998997, + "n": 30 + }, + "wm-text-similar-nsimilar": { + "p50": 20.894673999995575, + "p90": 28.01076099999773, + "mean": 22.988278166666472, + "min": 20.36417800000345, + "n": 30 + }, + "wm-text-iregex-niregex": { + "p50": 21.281176000004052, + "p90": 22.413277999992715, + "mean": 21.784303999999732, + "min": 20.296304000003147, + "n": 30 + }, + "wm-text-regex-nregex": { + "p50": 28.266448999987915, + "p90": 30.284576999998535, + "mean": 29.608283166665448, + "min": 27.24246399999538, + "n": 30 + }, + "wm-text-ilike-nilike": { + "p50": 26.666328000006615, + "p90": 27.59375600000203, + "mean": 27.494184933334086, + "min": 25.97645799999009, + "n": 30 + }, + "wm-int-eq-int32-max": { + "p50": 1.946870999992825, + "p90": 2.154573000007076, + "mean": 1.9536199000004368, + "min": 1.7755719999986468, + "n": 30 + }, + "wm-int-is-null": { + "p50": 1.8249989999894751, + "p90": 2.2115449999982957, + "mean": 1.8594463999999182, + "min": 1.6641340000060154, + "n": 30 + }, + "wm-int-eq-int32-min": { + "p50": 1.9298039999994216, + "p90": 2.088537000003271, + "mean": 1.9436474333313527, + "min": 1.7440829999977723, + "n": 30 + }, + "wm-numeric-eq-neq-trailing-zero": { + "p50": 1.8564730000070995, + "p90": 2.1382829999929527, + "mean": 1.9627816333328763, + "min": 1.6263380000018515, + "n": 30 + }, + "wm-numeric-gt-gte": { + "p50": 1.8959060000051977, + "p90": 2.249091000005137, + "mean": 2.890383266667777, + "min": 1.7446369999961462, + "n": 30 + }, + "wm-numeric-lt-lte": { + "p50": 1.7598509999952512, + "p90": 2.0336040000111097, + "mean": 1.7849167000002732, + "min": 1.5076820000103908, + "n": 30 + }, + "wm-numeric-is-null": { + "p50": 1.856406999999308, + "p90": 2.1338229999964824, + "mean": 1.8460347333331204, + "min": 1.6072449999919627, + "n": 30 + }, + "wm-numeric-eq-tiny-fraction": { + "p50": 1.2846889999927953, + "p90": 1.4728639999957522, + "mean": 1.3165893333318914, + "min": 1.2059390000067651, + "n": 30 + }, + "wm-numeric-eq-76-digits": { + "p50": 1.4064800000051036, + "p90": 1.5142380000033882, + "mean": 1.411813700000736, + "min": 1.2632920000032755, + "n": 30 + }, + "wm-float-eq-neq": { + "p50": 1.90688599999703, + "p90": 2.2370389999996405, + "mean": 1.9181458333318004, + "min": 1.676116999995429, + "n": 30 + }, + "wm-float-gt-gte-dbl-max": { + "p50": 1.963090999997803, + "p90": 2.183248999994248, + "mean": 1.9681110666676735, + "min": 1.7873230000113836, + "n": 30 + }, + "wm-float-lt-lte": { + "p50": 1.9233839999942575, + "p90": 2.2246009999944363, + "mean": 1.9448469333350658, + "min": 1.7563280000031227, + "n": 30 + }, + "wm-int-in-nin": { + "p50": 15.6102200000023, + "p90": 20.356646999993245, + "mean": 16.78676376666699, + "min": 14.58238499998697, + "n": 30 + }, + "wm-float-eq-infinity-literal": { + "p50": 1.4754699999903096, + "p90": 1.552616000000853, + "mean": 1.480177033333651, + "min": 1.3462690000014845, + "n": 30 + }, + "wm-float-is-null": { + "p50": 1.9214289999945322, + "p90": 2.282993999993778, + "mean": 1.9772893333322523, + "min": 1.7486729999945965, + "n": 30 + }, + "wm-float-in-nin": { + "p50": 2.0017579999985173, + "p90": 2.650154000002658, + "mean": 3.079399666665025, + "min": 1.7974669999966864, + "n": 30 + }, + "wm-float-eq-zero-matches-neg-zero": { + "p50": 1.6124540000018897, + "p90": 1.8532350000023143, + "mean": 1.6279312666655945, + "min": 1.409367000000202, + "n": 30 + }, + "wm-float-eq-nan": { + "p50": 1.42157400000724, + "p90": 1.654051999998046, + "mean": 1.5565006333330529, + "min": 1.228450000009616, + "n": 30 + }, + "wm-bool-eq-neq": { + "p50": 1.845590999990236, + "p90": 2.145866000006208, + "mean": 1.8598767000012837, + "min": 1.5703800000046613, + "n": 30 + }, + "wm-bool-gt-gte": { + "p50": 1.8096220000006724, + "p90": 2.108596000005491, + "mean": 1.8438314666661124, + "min": 1.569091000012122, + "n": 30 + }, + "wm-bool-lt-lte": { + "p50": 1.994858000005479, + "p90": 2.1625000000058208, + "mean": 1.9772784666667576, + "min": 1.6137019999878248, + "n": 30 + }, + "wm-bool-in-nin": { + "p50": 1.8828250000078697, + "p90": 2.268660000001546, + "mean": 2.885008599999613, + "min": 1.70808300000499, + "n": 30 + }, + "wm-ts-eq-neq": { + "p50": 1.9821039999951608, + "p90": 2.1685290000023087, + "mean": 1.9776093333333846, + "min": 1.808365999997477, + "n": 30 + }, + "wm-bool-is-null": { + "p50": 1.8991780000069411, + "p90": 2.2756310000113444, + "mean": 2.0162209666668787, + "min": 1.563280999995186, + "n": 30 + }, + "wm-ts-gt-gte": { + "p50": 1.8906629999983124, + "p90": 2.0784810000041034, + "mean": 1.8935959666661801, + "min": 1.7352410000021337, + "n": 30 + }, + "wm-ts-lt-lte": { + "p50": 1.908754999996745, + "p90": 2.1998989999992773, + "mean": 1.8996176999993621, + "min": 1.6017790000041714, + "n": 30 + }, + "wm-ts-eq-normalized-offset": { + "p50": 1.4207689999893773, + "p90": 1.516077000007499, + "mean": 1.4149416333336073, + "min": 1.2351269999926444, + "n": 30 + }, + "wm-ts-in-nin": { + "p50": 1.9071180000028107, + "p90": 2.2081620000099065, + "mean": 1.9310381333363087, + "min": 1.6826100000034785, + "n": 30 + }, + "wm-ts-is-null": { + "p50": 1.7861919999995735, + "p90": 2.1354299999948125, + "mean": 1.899134666667184, + "min": 1.525342000008095, + "n": 30 + }, + "wm-numeric-in-nin": { + "p50": 246.41562699999486, + "p90": 249.40022399999725, + "mean": 245.63523885714156, + "min": 240.26555999999982, + "n": 7 + }, + "wm-enum-is-null": { + "p50": 2.085010000009788, + "p90": 2.310534000003827, + "mean": 2.074169000000984, + "min": 1.8264920000074198, + "n": 30 + }, + "wm-enum-lt-lte-declaration-order": { + "p50": 11.661185999997542, + "p90": 12.272756999998819, + "mean": 11.684327799998574, + "min": 10.924593999996432, + "n": 30 + }, + "wm-enum-eq-neq": { + "p50": 20.06025700000464, + "p90": 21.080017000000225, + "mean": 20.811399600000975, + "min": 16.779702999992878, + "n": 30 + }, + "wm-array-eq-neq": { + "p50": 2.1284279999963474, + "p90": 2.589721999989706, + "mean": 3.1871518999988138, + "min": 1.9052729999966687, + "n": 30 + }, + "wm-array-gt-gte": { + "p50": 2.1265740000089863, + "p90": 2.504382999992231, + "mean": 2.148001799999717, + "min": 1.6926530000055209, + "n": 30 + }, + "wm-array-in-database-error": { + "p50": 1.4621430000115652, + "p90": 1.6138890000001993, + "mean": 1.4832349333325208, + "min": 1.4044429999921704, + "n": 30 + }, + "wm-array-lt-lte": { + "p50": 1.9553969999979017, + "p90": 2.419716000003973, + "mean": 2.056127366665654, + "min": 1.8543510000017704, + "n": 30 + }, + "wm-enum-in-nin": { + "p50": 12.908402000000933, + "p90": 17.36400900001172, + "mean": 14.18162916666576, + "min": 12.37814800000342, + "n": 30 + }, + "wm-enum-gt-gte": { + "p50": 38.63955700000224, + "p90": 56.70150599999761, + "mean": 40.96104630000094, + "min": 30.217132000005222, + "n": 30 + }, + "wm-array-is-null": { + "p50": 1.9801369999913732, + "p90": 2.350412999992841, + "mean": 2.0908363333330877, + "min": 1.7084730000060517, + "n": 30 + }, + "wm-array-contains-contained-in": { + "p50": 2.1606029999966267, + "p90": 2.4574739999952726, + "mean": 2.1635908000001414, + "min": 1.9018050000013318, + "n": 30 + }, + "wm-bigint-lt-lte-int-literal": { + "p50": 13.46138300000166, + "p90": 14.387484999999288, + "mean": 14.194388266668344, + "min": 13.140981000004103, + "n": 30 + }, + "wm-bigint-eq-neq": { + "p50": 154.21371600001294, + "p90": 158.76123800000641, + "mean": 153.17961820000346, + "min": 146.64550400000007, + "n": 10 + }, + "wm-in-duplicate-values": { + "p50": 1.6897680000110995, + "p90": 1.8782139999966603, + "mean": 1.7069550333340886, + "min": 1.5379199999879347, + "n": 30 + }, + "wm-bigint-in-nin-mixed-literals": { + "p50": 151.2357750000083, + "p90": 179.7398819999944, + "mean": 152.5140234999999, + "min": 145.10819600000104, + "n": 10 + }, + "wm-bigint-is-null": { + "p50": 149.68445499999507, + "p90": 161.48390399999334, + "mean": 151.2495179999998, + "min": 144.10401199999615, + "n": 10 + }, + "wm-in-single-value": { + "p50": 1.5309160000033444, + "p90": 1.672046000006958, + "mean": 1.5512422333335658, + "min": 1.3617939999967348, + "n": 30 + }, + "wm-is-null-true-with-eq": { + "p50": 1.9267740000068443, + "p90": 2.050694999998086, + "mean": 1.9208809666670277, + "min": 1.7759330000117188, + "n": 30 + }, + "wm-is-null-false-with-like": { + "p50": 2.0342579999996815, + "p90": 2.5419550000078743, + "mean": 2.9880096333319672, + "min": 1.8192640000052052, + "n": 30 + }, + "wm-bigint-eq-unquoted-64bit-literal": { + "p50": 7.696570000000065, + "p90": 8.018072000006214, + "mean": 7.686424533332077, + "min": 7.151490000003832, + "n": 30 + }, + "wm-jsonb-eq-nested-object": { + "p50": 1.4224859999958426, + "p90": 1.5650520000053803, + "mean": 1.4273856333321115, + "min": 1.2048629999917466, + "n": 30 + }, + "wm-jsonb-eq-empty-object": { + "p50": 1.4691949999978533, + "p90": 1.8123990000021877, + "mean": 1.5373648999996172, + "min": 1.2265909999987343, + "n": 30 + }, + "am-scalars-float8-full-matrix": { + "p50": 1.8047510000033071, + "p90": 2.1006150000030175, + "mean": 1.8567323000010219, + "min": 1.6342460000014398, + "n": 30 + }, + "am-user-int-full-matrix": { + "p50": 2.681758999999147, + "p90": 3.090608999991673, + "mean": 2.720225166665235, + "min": 2.4369089999963762, + "n": 30 + }, + "am-scalars-int-full-matrix": { + "p50": 1.6400830000056885, + "p90": 2.0245410000061383, + "mean": 1.6815460000007685, + "min": 1.4079039999924134, + "n": 30 + }, + "am-scalars-bigint-full-matrix": { + "p50": 1.9088629999896511, + "p90": 2.4272109999874374, + "mean": 1.946269233332229, + "min": 1.7089259999920614, + "n": 30 + }, + "wm-jsonb-eq-object-literal": { + "p50": 26.22667000000365, + "p90": 27.91471699999238, + "mean": 27.079490933333485, + "min": 24.610979999997653, + "n": 30 + }, + "am-scalars-bigdecimal-full-matrix": { + "p50": 1.567946999988635, + "p90": 1.9355650000070455, + "mean": 1.6942308000007567, + "min": 1.3943790000048466, + "n": 30 + }, + "wm-bigint-gt-gte": { + "p50": 348.7629920000036, + "p90": 359.67678799999703, + "mean": 350.491692399999, + "min": 346.352378999989, + "n": 5 + }, + "am-minmax-text-columns": { + "p50": 1.3921960000006948, + "p90": 1.7362869999924442, + "mean": 1.4567086333341044, + "min": 1.285982999994303, + "n": 30 + }, + "am-sim-int-full-matrix": { + "p50": 2.085097000002861, + "p90": 2.4778130000049714, + "mean": 2.1248572000006485, + "min": 1.9423939999978757, + "n": 30 + }, + "am-minmax-enum": { + "p50": 1.2825009999942267, + "p90": 1.5970410000008997, + "mean": 1.455758766666016, + "min": 1.172854999997071, + "n": 30 + }, + "am-minmax-text-unicode-empty": { + "p50": 1.448011000000406, + "p90": 1.6863149999990128, + "mean": 2.4099442666658435, + "min": 1.20771099999547, + "n": 30 + }, + "am-token-numeric-full-matrix": { + "p50": 36.585481999994954, + "p90": 42.37060900000506, + "mean": 37.31837123333389, + "min": 33.546271999992314, + "n": 30 + }, + "am-minmax-timestamptz": { + "p50": 1.4780769999924814, + "p90": 1.6149629999999888, + "mean": 1.4764695333331475, + "min": 1.2541939999937313, + "n": 30 + }, + "am-float8-sum-infinity-nan": { + "p50": 1.4547520000051009, + "p90": 1.6539489999995567, + "mean": 1.4629794666655167, + "min": 1.2111499999882653, + "n": 30 + }, + "am-float8-avg-nan": { + "p50": 1.5446030000020983, + "p90": 1.8121979999996256, + "mean": 1.6426250000008926, + "min": 1.1653569999907631, + "n": 30 + }, + "am-float8-minmax-infinity": { + "p50": 1.6304260000033537, + "p90": 1.738800999999512, + "mean": 1.580737866666459, + "min": 1.2879660000035074, + "n": 30 + }, + "am-minmax-user-mixed": { + "p50": 3.502632999996422, + "p90": 4.217143999994732, + "mean": 3.5711390999994665, + "min": 3.171002999995835, + "n": 30 + }, + "am-scalars-optint-null-handling": { + "p50": 1.6852880000078585, + "p90": 1.9108069999929285, + "mean": 1.703339533334171, + "min": 1.453406000000541, + "n": 30 + }, + "am-empty-minmax-mixed-types": { + "p50": 1.673990999988746, + "p90": 2.058950000006007, + "mean": 1.7327384666651293, + "min": 1.5609669999976177, + "n": 30 + }, + "am-empty-numeric-all-operators": { + "p50": 1.9517610000038985, + "p90": 2.3058030000102008, + "mean": 3.112562600000335, + "min": 1.66940899999463, + "n": 30 + }, + "am-empty-count-variants": { + "p50": 1.5408190000016475, + "p90": 1.6816059999982826, + "mean": 1.6181779000010768, + "min": 1.3832540000003064, + "n": 30 + }, + "am-empty-with-nodes": { + "p50": 1.6125559999927646, + "p90": 2.0677469999936875, + "mean": 1.7570312999979554, + "min": 1.4218970000074478, + "n": 30 + }, + "am-single-row-stddev-null": { + "p50": 1.81435600000259, + "p90": 2.0537210000038613, + "mean": 1.8411307333337996, + "min": 1.530230999997002, + "n": 30 + }, + "am-count-multi-columns": { + "p50": 2.7879119999997783, + "p90": 2.900742999991053, + "mean": 2.797980166665123, + "min": 2.5796189999964554, + "n": 30 + }, + "internal-raw-events-full": { + "p50": 1999.9975780000095, + "p90": 2136.00475800001, + "mean": 1963.2957310000056, + "min": 1753.8848569999973, + "n": 3 + }, + "am-count-distinct-with-nulls": { + "p50": 4.863742000001366, + "p90": 5.284181000009994, + "mean": 4.959523066665861, + "min": 4.691614000010304, + "n": 30 + }, + "am-count-distinct-no-columns": { + "p50": 1.823738000006415, + "p90": 2.000233999991906, + "mean": 1.8266953333310085, + "min": 1.6119369999942137, + "n": 30 + }, + "am-nested-agg-empty-owner": { + "p50": 1.7812820000108331, + "p90": 2.1467370000027586, + "mean": 1.8933320333337178, + "min": 1.5519710000080522, + "n": 30 + }, + "am-count-distinct-no-nulls": { + "p50": 16.428519000008237, + "p90": 17.379151999994065, + "mean": 17.6621597, + "min": 15.846321000004536, + "n": 30 + }, + "am-raw-bigint-sum": { + "p50": 13.578156000003219, + "p90": 15.564652000000933, + "mean": 14.772443633330598, + "min": 13.108062999992399, + "n": 30 + }, + "am-nested-count-distinct": { + "p50": 162.63724699997692, + "p90": 183.0933580000128, + "mean": 167.88327822221456, + "min": 155.61003899999196, + "n": 9 + }, + "am-raw-bigint-avg-vs-int-avg": { + "p50": 10.14361299999291, + "p90": 14.877597999991849, + "mean": 17.510091666665783, + "min": 9.798423000000184, + "n": 30 + }, + "am-root-distinct-on-aggregate": { + "p50": 183.70074700002442, + "p90": 196.17203499999596, + "mean": 184.5123774444445, + "min": 178.55453699998907, + "n": 9 + }, + "am-nested-agg-where-order-nodes": { + "p50": 1057.091704999999, + "p90": 1088.4343010000011, + "mean": 589.8874722500041, + "min": 106.92723800000385, + "n": 4 + }, + "am-raw-bigint-minmax": { + "p50": 18.643370000005234, + "p90": 24.938285999989603, + "mean": 20.15418526666569, + "min": 17.515687999984948, + "n": 30 + }, + "am-raw-int-sum-overflows-int32": { + "p50": 17.057196000008844, + "p90": 18.257238999998663, + "mean": 17.698881466670233, + "min": 15.940980000013951, + "n": 30 + }, + "am-raw-bigint-stddev-variance": { + "p50": 22.05511899999692, + "p90": 23.48654099999112, + "mean": 22.380439633331843, + "min": 21.490282000013394, + "n": 30 + }, + "am-meta-float4-matrix": { + "p50": 1.789422999980161, + "p90": 2.0578459999815095, + "mean": 1.82997336666643, + "min": 1.6360839999979362, + "n": 30 + }, + "am-meta-int-sum-nullable": { + "p50": 1.5592189999879338, + "p90": 1.724765999999363, + "mean": 1.6437708666664548, + "min": 1.413059999991674, + "n": 30 + }, + "am-chainmeta-float4-matrix": { + "p50": 1.6415360000100918, + "p90": 1.779264000011608, + "mean": 1.6594153333368014, + "min": 1.4583719999936875, + "n": 30 + }, + "am-user-avg-precision": { + "p50": 2.095907000009902, + "p90": 3.287815000017872, + "mean": 2.30883713333266, + "min": 1.8760290000063833, + "n": 30 + }, + "am-meta-minmax-timestamptz": { + "p50": 1.9889939999848139, + "p90": 2.446224000013899, + "mean": 2.072106600004675, + "min": 1.6028349999978673, + "n": 30 + }, + "am-agg-variables-where": { + "p50": 1.5704980000155047, + "p90": 1.7259020000055898, + "mean": 2.4485124333325077, + "min": 1.4053620000195224, + "n": 30 + }, + "am-error-min-bool": { + "p50": 0.9589990000240505, + "p90": 1.1624080000037793, + "mean": 0.993436233336494, + "min": 0.7801610000024084, + "n": 30 + }, + "am-error-sum-text-column": { + "p50": 0.9237219999777153, + "p90": 1.1069080000161193, + "mean": 0.9662106999991616, + "min": 0.7917000000015832, + "n": 30 + }, + "am-error-avg-timestamp": { + "p50": 1.0562320000026375, + "p90": 1.9143289999919944, + "mean": 1.2554718666651752, + "min": 0.9065240000199992, + "n": 30 + }, + "am-error-variance-enum": { + "p50": 1.021097999997437, + "p90": 1.6022850000008475, + "mean": 1.2640324999995451, + "min": 0.8353169999900274, + "n": 30 + }, + "am-error-count-unknown-column": { + "p50": 0.8932749999803491, + "p90": 1.0396039999905042, + "mean": 0.8941222333358989, + "min": 0.7329069999977946, + "n": 30 + }, + "am-nested-full-combo": { + "p50": 556.343664, + "p90": 556.472649000003, + "mean": 546.4052653333347, + "min": 526.399483000001, + "n": 3 + }, + "am-error-sum-jsonb": { + "p50": 0.9445319999940693, + "p90": 1.1156820000032894, + "mean": 1.0125279666652205, + "min": 0.8379249999998137, + "n": 30 + }, + "am-error-count-distinct-wrong-type": { + "p50": 0.9132530000060797, + "p90": 1.13828199999989, + "mean": 0.9595249333331595, + "min": 0.7792859999754, + "n": 30 + }, + "om-order-text-asc": { + "p50": 1.4436429999768734, + "p90": 1.7870640000037383, + "mean": 1.5436072333327806, + "min": 1.2758779999858234, + "n": 30 + }, + "om-order-numeric-bigint-asc": { + "p50": 1.606368000007933, + "p90": 2.2419470000022557, + "mean": 2.6602078666658295, + "min": 1.403191000019433, + "n": 30 + }, + "om-order-numeric-bigdecimal-desc": { + "p50": 1.5415400000056252, + "p90": 1.775822000025073, + "mean": 1.6298864999989746, + "min": 1.465874999994412, + "n": 30 + }, + "om-order-bool-desc": { + "p50": 1.612810000020545, + "p90": 2.0442179999954533, + "mean": 1.662202933334629, + "min": 1.4299389999941923, + "n": 30 + }, + "om-order-timestamp-desc": { + "p50": 1.6525000000256114, + "p90": 4.819866000005277, + "mean": 2.0470164999967286, + "min": 1.413044999993872, + "n": 30 + }, + "am-count-multi-columns-distinct": { + "p50": 861.8530219999957, + "p90": 884.9070130000036, + "mean": 866.2582303333329, + "min": 852.0146559999994, + "n": 3 + }, + "am-raw-count-distinct-text-and-pair": { + "p50": 211.71782599997823, + "p90": 212.41778599997633, + "mean": 210.5987867499898, + "min": 207.89326599999913, + "n": 8 + }, + "om-order-int-asc": { + "p50": 22.774124999996275, + "p90": 35.1868550000072, + "mean": 25.147747199997927, + "min": 21.12615499997628, + "n": 30 + }, + "om-order-int-desc": { + "p50": 21.5494469999976, + "p90": 30.906880000024103, + "mean": 24.605088299999867, + "min": 20.021982000005664, + "n": 30 + }, + "om-order-enum-desc": { + "p50": 14.178910999995423, + "p90": 16.86585900001228, + "mean": 15.32226293333321, + "min": 13.555243999988306, + "n": 30 + }, + "om-order-jsonb-asc": { + "p50": 1.5961359999782871, + "p90": 2.9733520000008866, + "mean": 1.8791954333360386, + "min": 1.3915909999923315, + "n": 30 + }, + "om-order-float-special-desc": { + "p50": 1.5721770000236575, + "p90": 1.7522089999984019, + "mean": 1.5752021000002665, + "min": 1.3091719999792986, + "n": 30 + }, + "om-order-optfloat-nan-asc": { + "p50": 1.5658669999975245, + "p90": 1.8567409999959636, + "mean": 1.6530037333335106, + "min": 1.4229789999953937, + "n": 30 + }, + "om-order-optfloat-nan-desc-nulls-last": { + "p50": 1.4738519999955315, + "p90": 1.7041160000080708, + "mean": 1.4875069666682976, + "min": 1.3058580000069924, + "n": 30 + }, + "om-order-directions-opt-int": { + "p50": 3.684827999997651, + "p90": 4.305588999995962, + "mean": 3.8080562666630917, + "min": 3.3582560000068042, + "n": 30 + }, + "om-order-directions-opt-float": { + "p50": 3.969068000005791, + "p90": 5.091103000013391, + "mean": 4.121372233334114, + "min": 3.2318369999993593, + "n": 30 + }, + "om-order-bigint-raw-events-asc": { + "p50": 296.039534999989, + "p90": 321.25281199999154, + "mean": 298.37565749999584, + "min": 284.4459429999988, + "n": 6 + }, + "om-order-directions-opt-text": { + "p50": 141.88048799999524, + "p90": 145.14888700001757, + "mean": 142.36655527272853, + "min": 139.34173600000213, + "n": 11 + }, + "om-order-bigint-raw-events-desc": { + "p50": 282.0364830000035, + "p90": 347.1296760000114, + "mean": 293.5044936666721, + "min": 275.9732490000024, + "n": 6 + }, + "om-order-directions-opt-bigint": { + "p50": 3.672059000004083, + "p90": 4.3279830000246875, + "mean": 4.75081806666761, + "min": 3.1511289999762084, + "n": 30 + }, + "om-order-multi-conflicting": { + "p50": 1.4692009999998845, + "p90": 1.68625400000019, + "mean": 1.4732226333318976, + "min": 1.2741289999976289, + "n": 30 + }, + "om-order-multi-conflicting-flipped": { + "p50": 1.526519000006374, + "p90": 1.7878930000006221, + "mean": 1.620254633333146, + "min": 1.372218000004068, + "n": 30 + }, + "om-order-directions-opt-timestamp": { + "p50": 3.8268479999969713, + "p90": 4.414418000000296, + "mean": 3.87654690000248, + "min": 3.4053399999975227, + "n": 30 + }, + "om-order-multi-list-respects-order": { + "p50": 1.555082000006223, + "p90": 1.8194849999854341, + "mean": 2.5131987333336534, + "min": 1.381308000010904, + "n": 30 + }, + "om-order-object-keys-logindex-first": { + "p50": 1.4636980000068434, + "p90": 1.68204000001424, + "mean": 1.4921126333385473, + "min": 1.2933870000124443, + "n": 30 + }, + "om-order-object-keys-blocknumber-first": { + "p50": 1.5431030000036117, + "p90": 1.802456000004895, + "mean": 1.5661693666663874, + "min": 1.3627090000081807, + "n": 30 + }, + "om-order-mixed-list-with-multikey-object": { + "p50": 1.6026750000019092, + "p90": 1.8180750000174157, + "mean": 1.7042448333348148, + "min": 1.444839999981923, + "n": 30 + }, + "om-order-directions-opt-enum": { + "p50": 3.6687850000162143, + "p90": 4.041652999992948, + "mean": 3.6833339999992556, + "min": 3.2556340000010096, + "n": 30 + }, + "om-order-same-column-twice-list": { + "p50": 1.518458999984432, + "p90": 1.7915440000069793, + "mean": 1.5560676000032496, + "min": 1.3406530000211205, + "n": 30 + }, + "om-order-array-rel-aggregate-count-desc": { + "p50": 50.71990800002823, + "p90": 63.10121200000867, + "mean": 53.06185499999817, + "min": 49.39519399998244, + "n": 29 + }, + "om-introspect-user-order-by": { + "p50": 1.119451999955345, + "p90": 1.3519910000031814, + "mean": 1.2429214333281076, + "min": 0.9547579999780282, + "n": 30 + }, + "om-introspect-token-aggregate-order-by": { + "p50": 1.3416659999638796, + "p90": 1.5731049999594688, + "mean": 1.3653150666640916, + "min": 1.2053089999826625, + "n": 30 + }, + "om-order-jsonb-desc-raw-events": { + "p50": 573.5660830000124, + "p90": 574.6896649999835, + "mean": 570.6962749999948, + "min": 563.8330769999884, + "n": 3 + }, + "om-order-array-rel-aggregate-max": { + "p50": 253.46779000002425, + "p90": 262.0981230000034, + "mean": 254.381367500008, + "min": 250.97422299999744, + "n": 6 + }, + "om-distinct-multi-prefix-swapped": { + "p50": 1.6444259999552742, + "p90": 2.0643830000190064, + "mean": 1.6888712999934796, + "min": 1.4518589999643154, + "n": 30 + }, + "om-error-order-unknown-column": { + "p50": 0.8894050000235438, + "p90": 1.0019210000173189, + "mean": 0.8952061000008447, + "min": 0.7447690000408329, + "n": 30 + }, + "om-error-order-array-rel-column": { + "p50": 0.8627389999455772, + "p90": 0.9704059999785386, + "mean": 0.8596744999968602, + "min": 0.6840579999843612, + "n": 30 + }, + "om-error-order-duplicate-key-in-object": { + "p50": 0.8580349999829195, + "p90": 1.0695730000152253, + "mean": 0.8780900333328948, + "min": 0.6786069999798201, + "n": 30 + }, + "om-error-distinct-not-first-in-order": { + "p50": 0.9853889999794774, + "p90": 1.2290009999996983, + "mean": 1.0722721333246834, + "min": 0.716677000047639, + "n": 30 + }, + "om-error-distinct-unknown-column": { + "p50": 0.9346820000209846, + "p90": 3.017399000003934, + "mean": 2.177305400004843, + "min": 0.7162309999694116, + "n": 30 + }, + "vr-var-string-where": { + "p50": 1.6421669999836013, + "p90": 2.0124930000165477, + "mean": 1.6896453999991838, + "min": 1.3567809999804012, + "n": 30 + }, + "om-distinct-same-column-twice": { + "p50": 165.70853200001875, + "p90": 173.7904419999686, + "mean": 166.41769689999637, + "min": 161.13492700003553, + "n": 10 + }, + "vr-var-int-limit-offset": { + "p50": 1.8645719999913126, + "p90": 2.497092999983579, + "mean": 1.9905314666665315, + "min": 1.5479819999891333, + "n": 30 + }, + "om-distinct-extra-order-keys": { + "p50": 224.42872800002806, + "p90": 230.5299740000046, + "mean": 223.16233871428994, + "min": 214.4861840000376, + "n": 7 + }, + "vr-var-float8-number": { + "p50": 2.086156999983359, + "p90": 3.110129999986384, + "mean": 2.1535210666634765, + "min": 1.5235069999471307, + "n": 30 + }, + "vr-var-float8-string-coerced": { + "p50": 1.6097219999646768, + "p90": 1.9706979999900796, + "mean": 1.6958304333364747, + "min": 1.3860270000295714, + "n": 30 + }, + "vr-var-boolean-string-in-where-coerced": { + "p50": 1.8144079999765381, + "p90": 2.6345020000007935, + "mean": 2.024724399993041, + "min": 1.5612790000159293, + "n": 30 + }, + "vr-error-boolean-string-in-include-directive": { + "p50": 0.8534050000016578, + "p90": 1.0738840000121854, + "mean": 0.881571566668572, + "min": 0.732819999975618, + "n": 30 + }, + "vr-var-numeric-as-string": { + "p50": 1.6094869999797083, + "p90": 2.587498999957461, + "mean": 1.8129005666686377, + "min": 1.3792170000378974, + "n": 30 + }, + "vr-var-numeric-as-number": { + "p50": 1.633596999978181, + "p90": 1.9384870000067167, + "mean": 2.6557485666669285, + "min": 1.3552360000321642, + "n": 30 + }, + "vr-var-numeric-decimal-number": { + "p50": 1.7508619999862276, + "p90": 3.187949000042863, + "mean": 2.086997733336951, + "min": 1.531944000045769, + "n": 30 + }, + "vr-var-timestamptz-string": { + "p50": 1.548858999973163, + "p90": 1.9015609999769367, + "mean": 1.5613173999940044, + "min": 1.3102459999499843, + "n": 30 + }, + "vr-var-jsonb-object-contains": { + "p50": 1.6947800000198185, + "p90": 1.7865039999596775, + "mean": 1.676712666663419, + "min": 1.5200459999614395, + "n": 30 + }, + "vr-error-enum-scalar-invalid-value": { + "p50": 1.485121000034269, + "p90": 1.634368999977596, + "mean": 1.5035345000079057, + "min": 1.339114000031259, + "n": 30 + }, + "vr-var-string-list-in": { + "p50": 1.6371999999973923, + "p90": 1.9827299999888055, + "mean": 1.67292333333365, + "min": 1.450557000003755, + "n": 30 + }, + "vr-var-jsonb-unicode-contains": { + "p50": 1.4716219999827445, + "p90": 3.603189999994356, + "mean": 2.5717963666616317, + "min": 1.2555919999722391, + "n": 30 + }, + "vr-var-enum-scalar-accounttype": { + "p50": 5.8596330000436865, + "p90": 6.8677040000329725, + "mean": 6.0209570333419835, + "min": 5.489380000042729, + "n": 30 + }, + "vr-error-string-list-int-element": { + "p50": 0.7532249999931082, + "p90": 0.8810709999524988, + "mean": 0.7596005333335294, + "min": 0.6452890000073239, + "n": 30 + }, + "vr-var-string-list-single-value-coercion": { + "p50": 1.5390609999885783, + "p90": 1.8231489999452606, + "mean": 1.648771200001162, + "min": 1.3844769999850541, + "n": 30 + }, + "vr-var-order-by-list": { + "p50": 1.4634160000132397, + "p90": 1.7456269999966025, + "mean": 1.5573407666680092, + "min": 1.2739280000096187, + "n": 30 + }, + "vr-var-order-by-enum-in-object-default": { + "p50": 1.31937000004109, + "p90": 1.4763550000498071, + "mean": 1.3279474666710789, + "min": 1.1396660000318661, + "n": 30 + }, + "om-order-object-rel-owner-id": { + "p50": 673.0887719999882, + "p90": 747.4880670000275, + "mean": 696.256472333344, + "min": 668.1925780000165, + "n": 3 + }, + "vr-var-select-column-single-value-coercion": { + "p50": 134.53704900003504, + "p90": 140.09627400001045, + "mean": 135.59108183332137, + "min": 127.8913220000104, + "n": 12 + }, + "vr-var-select-column-distinct-on": { + "p50": 207.4600039999932, + "p90": 219.12317399994936, + "mean": 209.55943624999054, + "min": 205.03322400001343, + "n": 8 + }, + "om-order-object-rel-two-levels": { + "p50": 1026.527597999986, + "p90": 1069.5773120000085, + "mean": 1038.7741793333262, + "min": 1020.217627999984, + "n": 3 + }, + "vr-default-bool-exp-used": { + "p50": 1.5315319999936037, + "p90": 1.8410429999930784, + "mean": 1.573184866667725, + "min": 1.3993030000128783, + "n": 30 + }, + "vr-default-int-overridden": { + "p50": 1.3644990000175312, + "p90": 1.4978410000330769, + "mean": 1.3829731333379944, + "min": 1.2866870000143535, + "n": 30 + }, + "vr-default-null-override": { + "p50": 1.3805670000147074, + "p90": 1.5992739999783225, + "mean": 1.4067199666673937, + "min": 1.220573999977205, + "n": 30 + }, + "vr-var-missing-variables-object": { + "p50": 1.3405990000464953, + "p90": 1.5215660000103526, + "mean": 1.3564416333353924, + "min": 1.1904180000419728, + "n": 30 + }, + "vr-error-int-var-float-json": { + "p50": 0.7213820000179112, + "p90": 0.850161999987904, + "mean": 0.7372749666722181, + "min": 0.6353939999826252, + "n": 30 + }, + "vr-var-null-for-nullable-args": { + "p50": 1.3547160000307485, + "p90": 1.4926010000053793, + "mean": 1.381513633330663, + "min": 1.2760319999651983, + "n": 30 + }, + "vr-error-int-var-string-json": { + "p50": 0.72034200001508, + "p90": 0.9650580000015907, + "mean": 0.8242976000008639, + "min": 0.6098169999895617, + "n": 30 + }, + "vr-error-numeric-var-bool": { + "p50": 0.7223530000192113, + "p90": 0.9054759999853559, + "mean": 0.7465806333328753, + "min": 0.6143469999660738, + "n": 30 + }, + "vr-error-extra-undeclared-variable": { + "p50": 0.6962120000389405, + "p90": 0.8690699999569915, + "mean": 0.76677909999853, + "min": 0.5689150000107475, + "n": 30 + }, + "vr-error-id-type-variable": { + "p50": 0.7250789999961853, + "p90": 0.8272609999985434, + "mean": 0.7350931333339152, + "min": 0.5941369999782182, + "n": 30 + }, + "vr-error-opname-with-anonymous-op": { + "p50": 0.5543609999585897, + "p90": 0.7193639999604784, + "mean": 0.664099899995684, + "min": 0.4290069999988191, + "n": 30 + }, + "vr-admin-mutation-insert-unknown-table": { + "p50": 0.6746890000067651, + "p90": 0.8641270000371151, + "mean": 0.6990600000077393, + "min": 0.6044359999941662, + "n": 30 + }, + "vr-opname-selects-op-with-vars": { + "p50": 1.5240689999773167, + "p90": 1.860257999971509, + "mean": 2.4889254333393183, + "min": 1.3838220000034198, + "n": 30 + }, + "vr-opname-query-beside-mutation-public": { + "p50": 1.3378289999673143, + "p90": 1.6995050000259653, + "mean": 1.5034923333325423, + "min": 1.2505789999850094, + "n": 30 + }, + "vr-directive-include-fragment-spread": { + "p50": 1.4415210000006482, + "p90": 1.6239250000216998, + "mean": 1.4669492333370726, + "min": 1.3128199999919161, + "n": 30 + }, + "vr-directive-include-fragment-spread-false": { + "p50": 1.491292999999132, + "p90": 1.6890849999617785, + "mean": 1.5690923666678525, + "min": 1.3577039999654517, + "n": 30 + }, + "vr-directive-skip-inline-fragment": { + "p50": 1.413691000023391, + "p90": 1.556306999991648, + "mean": 1.4349281000031624, + "min": 1.2431370000122115, + "n": 30 + }, + "vr-error-directive-include-on-operation": { + "p50": 0.7053939999896102, + "p90": 0.8942120000137947, + "mean": 0.7368874666610888, + "min": 0.6294810000108555, + "n": 30 + }, + "vr-var-nested-relationship-args": { + "p50": 369.2809250000282, + "p90": 372.2869139999966, + "mean": 369.31772980000824, + "min": 366.4708020000253, + "n": 5 + }, + "vr-error-same-alias-conflicting-args": { + "p50": 0.7378240000107326, + "p90": 1.3258899999782443, + "mean": 1.051224699994782, + "min": 0.641116000013426, + "n": 30 + }, + "vr-alias-duplicate-root-different-args": { + "p50": 2.465884000004735, + "p90": 2.662280999997165, + "mean": 2.4416350666666404, + "min": 2.2613089999649674, + "n": 30 + }, + "ss-row-nonarray-scalar-1": { + "p50": 2.0607559999916703, + "p90": 2.646046000008937, + "mean": 2.189685833331896, + "min": 1.7979649999761023, + "n": 30 + }, + "ss-row-nonarray-scalar-nulls": { + "p50": 1.908242000034079, + "p90": 2.2809119999874383, + "mean": 1.9255375666660257, + "min": 1.6072740000090562, + "n": 30 + }, + "ss-row-nonarray-scalar-extremes": { + "p50": 1.9160590000101365, + "p90": 2.357047000026796, + "mean": 1.929308399996565, + "min": 1.6319839999778196, + "n": 30 + }, + "vr-var-bool-exp-token": { + "p50": 417.63562699995236, + "p90": 459.49783099995693, + "mean": 424.49686074999045, + "min": 410.0477580000297, + "n": 4 + }, + "ss-row-nonarray-scalar-special-float": { + "p50": 1.896565999952145, + "p90": 2.2741880000103265, + "mean": 2.042690600002728, + "min": 1.6898159999982454, + "n": 30 + }, + "ss-row-nonarray-scalar-neg-inf": { + "p50": 1.8826129999943078, + "p90": 2.417075000004843, + "mean": 1.9529695333389099, + "min": 1.710984000004828, + "n": 30 + }, + "ss-row-nonarray-scalar-unicode": { + "p50": 1.9860800000024028, + "p90": 2.4087900000158697, + "mean": 3.0994953999936117, + "min": 1.7107869999599643, + "n": 30 + }, + "ss-row-nonarray-scalar-quotes": { + "p50": 1.8340320000424981, + "p90": 2.3022950000013225, + "mean": 1.8744281000050251, + "min": 1.6914049999904819, + "n": 30 + }, + "ss-row-nonarray-scalar-empty": { + "p50": 1.742379000002984, + "p90": 2.2456569999922067, + "mean": 1.798991333328498, + "min": 1.576935000019148, + "n": 30 + }, + "ss-row-alltypes-all-1": { + "p50": 1.8973760000080802, + "p90": 2.380298000003677, + "mean": 2.0234049000020606, + "min": 1.638639000011608, + "n": 30 + }, + "ss-row-alltypes-all-empty-arrays": { + "p50": 1.7778829999733716, + "p90": 2.3401559999911115, + "mean": 1.8472599666604461, + "min": 1.624695000005886, + "n": 30 + }, + "ss-row-alltypes-all-array-edge": { + "p50": 2.204245000029914, + "p90": 2.5236250000307336, + "mean": 2.2404085333323263, + "min": 1.9078819999704137, + "n": 30 + }, + "ss-row-alltypes-all-json-string": { + "p50": 2.0215960000059567, + "p90": 2.390516999992542, + "mean": 2.132847366666344, + "min": 1.7852480000001378, + "n": 30 + }, + "ss-row-alltypes-all-json-number": { + "p50": 1.987024999980349, + "p90": 3.310531999974046, + "mean": 3.0566264999972192, + "min": 1.7629070000257343, + "n": 30 + }, + "ss-row-alltypes-all-json-null": { + "p50": 1.8839900000020862, + "p90": 2.1672859999816865, + "mean": 1.9013815666665324, + "min": 1.6876509999856353, + "n": 30 + }, + "ss-row-alltypes-all-json-unicode": { + "p50": 1.8834449999849312, + "p90": 2.332777999981772, + "mean": 1.9258509333342468, + "min": 1.6519960000296123, + "n": 30 + }, + "ss-row-alltypes-all-json-bool": { + "p50": 1.93917699996382, + "p90": 2.231766000040807, + "mean": 1.9787701333368508, + "min": 1.7162290000123903, + "n": 30 + }, + "ss-row-precision-prec-1": { + "p50": 1.7088869999861345, + "p90": 2.0725819999934174, + "mean": 1.791411266673822, + "min": 1.4915150000015274, + "n": 30 + }, + "ss-row-precision-prec-nulls": { + "p50": 1.432983000006061, + "p90": 1.6233820000197738, + "mean": 1.4783730999974067, + "min": 1.2853979999781586, + "n": 30 + }, + "vr-fragment-chain-deep": { + "p50": 328.8752439999953, + "p90": 333.868163999985, + "mean": 330.22340459999396, + "min": 328.34577899996657, + "n": 5 + }, + "ss-row-precision-prec-2": { + "p50": 1.5800619999645278, + "p90": 1.794198999996297, + "mean": 1.5989054333321595, + "min": 1.388658000039868, + "n": 30 + }, + "ss-row-bigdecimal-bd-2": { + "p50": 1.3690330000245012, + "p90": 1.703483999997843, + "mean": 2.3054234999930485, + "min": 1.15671900002053, + "n": 30 + }, + "ss-row-bigdecimal-bd-1": { + "p50": 1.3296010000049137, + "p90": 1.6440769999753684, + "mean": 1.3847902666641554, + "min": 1.2135800000396557, + "n": 30 + }, + "ss-row-bigdecimal-bd-3": { + "p50": 1.4195349999936298, + "p90": 1.7712109999847598, + "mean": 1.5453424666600768, + "min": 1.2092399999964982, + "n": 30 + }, + "ss-row-bigdecimal-bd-4": { + "p50": 1.3039139999891631, + "p90": 1.6927980000036769, + "mean": 1.3613390333368443, + "min": 1.0858500000322238, + "n": 30 + }, + "ss-row-bigdecimal-bd-5": { + "p50": 1.3588969999691471, + "p90": 1.5267369999783114, + "mean": 1.3709862333295557, + "min": 1.1549409999861382, + "n": 30 + }, + "ss-row-timestamp-ts-micro": { + "p50": 1.312067000020761, + "p90": 1.469890000007581, + "mean": 1.3289687666634564, + "min": 1.1772629999904893, + "n": 30 + }, + "ss-row-timestamp-ts-epoch": { + "p50": 1.2647979999892414, + "p90": 1.4235899999621324, + "mean": 1.2964291333317912, + "min": 1.1667860000161454, + "n": 30 + }, + "ss-row-timestamp-ts-milli": { + "p50": 1.2939030000125058, + "p90": 1.6936279999790713, + "mean": 1.4141082666659106, + "min": 1.1623099999851547, + "n": 30 + }, + "ss-row-timestamp-ts-pre-epoch": { + "p50": 1.4839190000202507, + "p90": 1.6317379999672994, + "mean": 1.463581766669328, + "min": 1.2137199999997392, + "n": 30 + }, + "ss-row-timestamp-ts-future": { + "p50": 1.4672889999928884, + "p90": 1.6215489999740385, + "mean": 1.52225079999965, + "min": 1.2070500000263564, + "n": 30 + }, + "ss-row-timestamp-ts-zoned": { + "p50": 1.3827370000071824, + "p90": 1.4947459999821149, + "mean": 1.3960180000013982, + "min": 1.2988400000031106, + "n": 30 + }, + "vr-typename-aggregate-admin": { + "p50": 363.79784199997084, + "p90": 421.8487399999867, + "mean": 376.9855812499736, + "min": 359.77826699998695, + "n": 4 + }, + "ss-json-path-key": { + "p50": 1.4958040000055917, + "p90": 1.6995199999655597, + "mean": 1.5003082666681924, + "min": 1.360768000013195, + "n": 30 + }, + "ss-arrays-numeric-precision-string-vs-number": { + "p50": 1.8656250000349246, + "p90": 4.846857999975327, + "mean": 2.9881924000006013, + "min": 1.6596780000254512, + "n": 30 + }, + "ss-arrays-alltypes-string-vs-number": { + "p50": 1.8491829999838956, + "p90": 2.069776999996975, + "mean": 1.8811767666658852, + "min": 1.7109850000124425, + "n": 30 + }, + "ss-json-path-root-index": { + "p50": 1.5217210000264458, + "p90": 1.6773790000006557, + "mean": 1.5298960666599062, + "min": 1.3530299999983981, + "n": 30 + }, + "ss-json-path-nested-index": { + "p50": 1.4537100000306964, + "p90": 1.7176230000331998, + "mean": 1.5959366333399279, + "min": 1.3359770000097342, + "n": 30 + }, + "ss-json-path-missing-nested": { + "p50": 1.6191509999916889, + "p90": 1.908588000049349, + "mean": 1.6164988000004086, + "min": 1.2897119999979623, + "n": 30 + }, + "ss-json-path-on-scalar-value": { + "p50": 1.451952000032179, + "p90": 1.7000540000153705, + "mean": 1.474920566676883, + "min": 1.3080460000201128, + "n": 30 + }, + "ss-json-path-on-json-null": { + "p50": 1.5413819999666885, + "p90": 1.6561010000295937, + "mean": 1.5287731666622373, + "min": 1.3230840000323951, + "n": 30 + }, + "ss-json-path-dollar-root": { + "p50": 1.4045820000465028, + "p90": 1.5782539999927394, + "mean": 1.440352333339009, + "min": 1.2028949999948964, + "n": 30 + }, + "ss-json-path-no-dollar-prefix": { + "p50": 1.430884999979753, + "p90": 1.8050259999581613, + "mean": 2.3995293000014497, + "min": 1.1828460000106134, + "n": 30 + }, + "ss-json-path-unicode-key": { + "p50": 1.419867999968119, + "p90": 1.5699989999993704, + "mean": 1.4196655666610847, + "min": 1.217789999966044, + "n": 30 + }, + "ss-json-path-empty-string-error": { + "p50": 0.887901000038255, + "p90": 1.0178210000158288, + "mean": 0.8659848666691687, + "min": 0.7038099999772385, + "n": 30 + }, + "ss-json-path-variable": { + "p50": 1.5791190000018105, + "p90": 1.7217819999787025, + "mean": 1.5876848666734682, + "min": 1.411627999972552, + "n": 30 + }, + "ss-bypk-special-chars-full": { + "p50": 1.5062770000076853, + "p90": 1.6985820000409149, + "mean": 1.5408768000022974, + "min": 1.3611839999794029, + "n": 30 + }, + "ss-json-alias-three-paths": { + "p50": 1.5904030000092462, + "p90": 1.7517750000115484, + "mean": 1.5971923000004609, + "min": 1.3852199999964796, + "n": 30 + }, + "ss-bypk-special-chars-variable": { + "p50": 1.4938269999693148, + "p90": 1.6218799999915063, + "mean": 1.4901233333279378, + "min": 1.2976800000178628, + "n": 30 + }, + "ss-typename-only-by-pk": { + "p50": 1.459290000027977, + "p90": 1.7085180000285618, + "mean": 1.4693394666692863, + "min": 1.3454239999991842, + "n": 30 + }, + "ss-typename-only-list": { + "p50": 1.3528270000242628, + "p90": 1.4779140000464395, + "mean": 1.356358700003087, + "min": 1.1907200000132434, + "n": 30 + }, + "ss-field-order-reverse-schema": { + "p50": 1.8755050000036135, + "p90": 2.433973999985028, + "mean": 2.063457766668095, + "min": 1.7005369999678805, + "n": 30 + }, + "ss-field-order-interleaved": { + "p50": 1.5233579999767244, + "p90": 1.7116099999984726, + "mean": 1.5528613000060432, + "min": 1.380224000022281, + "n": 30 + }, + "rm-exists-b-a-pair": { + "p50": 2.296794999972917, + "p90": 2.795817000034731, + "mean": 2.328517299995292, + "min": 1.980622000002768, + "n": 30 + }, + "rm-exists-c-d-pair": { + "p50": 2.0121299999882467, + "p90": 2.3390629999921657, + "mean": 2.984098633332178, + "min": 1.7940870000165887, + "n": 30 + }, + "rm-exists-collection-tokens-pair": { + "p50": 2.8792930000345223, + "p90": 3.414463999972213, + "mean": 2.987584000001273, + "min": 2.5889469999819994, + "n": 30 + }, + "rm-exists-bare-vs-predicate": { + "p50": 2.7855039999703877, + "p90": 3.2663380000158213, + "mean": 2.830546399997547, + "min": 2.449659000034444, + "n": 30 + }, + "rm-exists-user-tokens-pair": { + "p50": 65.4427559999749, + "p90": 83.85518100002082, + "mean": 68.28926990908803, + "min": 62.332040999957826, + "n": 22 + }, + "rm-object-exists-vs-fk-not-null": { + "p50": 19.968883999972604, + "p90": 25.99596599995857, + "mean": 21.54393086665853, + "min": 19.31753200001549, + "n": 30 + }, + "rm-object-exists-gravatar-pair": { + "p50": 25.638801000022795, + "p90": 28.609991999983322, + "mean": 26.857281366669728, + "min": 24.455575000029057, + "n": 30 + }, + "rm-object-not-exists-b-c": { + "p50": 1.78209799999604, + "p90": 1.9838079999899492, + "mean": 1.7570231333336173, + "min": 1.4570809999713674, + "n": 30 + }, + "rm-object-not-exists-gravatar-owner": { + "p50": 4.197280999971554, + "p90": 4.606017000041902, + "mean": 4.222408966663837, + "min": 3.619382999953814, + "n": 30 + }, + "rm-object-exists-a-b-pair": { + "p50": 2.3109069999773055, + "p90": 2.8558429999975488, + "mean": 2.4532106666728697, + "min": 1.8085310000460595, + "n": 30 + }, + "rm-dangling-token-collection": { + "p50": 1.7454879999859259, + "p90": 2.0761119999806397, + "mean": 2.7177383333289375, + "min": 1.4895070000202395, + "n": 30 + }, + "rm-dangling-token-owner": { + "p50": 1.6426870000432245, + "p90": 2.2296510000014678, + "mean": 1.887938433328721, + "min": 1.44617000001017, + "n": 30 + }, + "rm-dangling-gravatar-owner": { + "p50": 1.6634220000123605, + "p90": 2.025052000011783, + "mean": 1.6647539666640416, + "min": 1.3993939999490976, + "n": 30 + }, + "rm-dangling-user-gravatar": { + "p50": 1.5750109999789856, + "p90": 1.7874689999734983, + "mean": 1.5861465333320666, + "min": 1.3314100000425242, + "n": 30 + }, + "rm-dangling-b-c-all-rows": { + "p50": 1.5728349999990314, + "p90": 1.7859640000388026, + "mean": 1.5901209000032395, + "min": 1.4189710000064224, + "n": 30 + }, + "rm-dangling-a-b": { + "p50": 1.5283889999845996, + "p90": 1.9986229999922216, + "mean": 1.677854599999652, + "min": 1.334430000046268, + "n": 30 + }, + "rm-dangling-d-via-rel-vs-column": { + "p50": 1.958232999953907, + "p90": 2.364069000002928, + "mean": 1.9760250000030888, + "min": 1.6168409999809228, + "n": 30 + }, + "rm-multihop-a-b-c-d": { + "p50": 1.852673000015784, + "p90": 2.1153359999880195, + "mean": 1.8797512666671536, + "min": 1.6653279999736696, + "n": 30 + }, + "rm-object-not-exists-token-owner": { + "p50": 162.56714400002966, + "p90": 168.6137919999892, + "mean": 162.33214249999727, + "min": 157.4882970000035, + "n": 10 + }, + "rm-multihop-c-both-directions": { + "p50": 1.8959809999796562, + "p90": 2.2119710000115447, + "mean": 2.859026933335311, + "min": 1.7044849999947473, + "n": 30 + }, + "rm-multihop-b-both-directions": { + "p50": 1.8295039999647997, + "p90": 2.1979759999667294, + "mean": 1.9466270333214197, + "min": 1.6568899999838322, + "n": 30 + }, + "rm-multihop-d-plain-column-filter": { + "p50": 1.8274640000308864, + "p90": 2.221414999978151, + "mean": 1.8735142666671891, + "min": 1.6654119999730028, + "n": 30 + }, + "rm-multihop-a-b-a-siblings": { + "p50": 1.752003000001423, + "p90": 2.0913580000051297, + "mean": 1.792052266667209, + "min": 1.5580519999493845, + "n": 30 + }, + "rm-child-window-beyond-rows": { + "p50": 2.087831999990158, + "p90": 2.35870199999772, + "mean": 2.2007537333314153, + "min": 1.8875049999915063, + "n": 30 + }, + "rm-object-not-exists-token-collection": { + "p50": 52.47487299999921, + "p90": 57.622514999995474, + "mean": 54.90926124137859, + "min": 51.50594000000274, + "n": 29 + }, + "rm-cross-and-parent-child": { + "p50": 2.7357499999925494, + "p90": 3.3495049999910407, + "mean": 2.8266958333357857, + "min": 2.4559400000143796, + "n": 30 + }, + "rm-cross-not-inside-rel": { + "p50": 88.30162500002189, + "p90": 92.80198099999689, + "mean": 89.61385635293418, + "min": 85.67187999997986, + "n": 17 + }, + "rm-cross-and-inside-rel": { + "p50": 2.371171000006143, + "p90": 2.704827000037767, + "mean": 2.4072828666714488, + "min": 2.1769959999946877, + "n": 30 + }, + "rm-child-all-args-collection-tokens": { + "p50": 202.5070570000098, + "p90": 220.38657500001136, + "mean": 202.35700112499762, + "min": 184.625875000027, + "n": 8 + }, + "rm-cross-or-two-rel-paths": { + "p50": 19.170343999983743, + "p90": 31.03660699998727, + "mean": 20.866653700000217, + "min": 18.444750000024214, + "n": 30 + }, + "rm-same-table-two-paths": { + "p50": 57.05019799998263, + "p90": 76.16270499996608, + "mean": 60.92111192000331, + "min": 54.26533300004667, + "n": 25 + }, + "rm-same-table-b-self-join": { + "p50": 1.84003100002883, + "p90": 2.376786999986507, + "mean": 1.900403166670973, + "min": 1.529787999985274, + "n": 30 + }, + "rm-child-all-args-user-tokens": { + "p50": 468.74293100001523, + "p90": 479.31602299999213, + "mean": 468.565783500002, + "min": 462.1653739999747, + "n": 4 + }, + "rm-deep-self-nesting-depth7": { + "p50": 2.6823779999976978, + "p90": 3.434101999970153, + "mean": 2.7849382666735134, + "min": 2.389872000028845, + "n": 30 + }, + "rm-deep-where-self-referential": { + "p50": 1.7090850000386126, + "p90": 2.7160150000127032, + "mean": 2.813492133334512, + "min": 1.5386440000147559, + "n": 30 + }, + "rm-agg-order-count-asc-empty-first": { + "p50": 11.23352100001648, + "p90": 11.624450999952387, + "mean": 11.973684266661682, + "min": 10.752815999963786, + "n": 30 + }, + "rm-agg-order-max-nulls-first": { + "p50": 11.41965400002664, + "p90": 12.328393000003416, + "mean": 11.594193433333809, + "min": 10.875900000042748, + "n": 30 + }, + "rm-cross-or-three-branches": { + "p50": 440.2045839999919, + "p90": 455.4709220000077, + "mean": 441.1812460000074, + "min": 433.8102690000087, + "n": 4 + }, + "rm-same-table-token-and-sibling": { + "p50": 141.99459399998887, + "p90": 149.2082769999979, + "mean": 143.88548645454418, + "min": 135.38760499999626, + "n": 11 + }, + "rm-alias-swap-column-and-rel": { + "p50": 1.8482400000211783, + "p90": 2.1975709999678656, + "mean": 1.8900675666615523, + "min": 1.6855860000359826, + "n": 30 + }, + "rm-alias-user-gravatar-shadow": { + "p50": 1.7905180000234395, + "p90": 2.1042690000031143, + "mean": 1.9099839000050756, + "min": 1.6892220000154339, + "n": 30 + }, + "rm-alias-conflict-rel-vs-column": { + "p50": 0.6841380000114441, + "p90": 0.8827370000071824, + "mean": 0.7191244000006312, + "min": 0.607166999951005, + "n": 30 + }, + "em-arg-where-as-list": { + "p50": 0.6578449999797158, + "p90": 0.7995719999889843, + "mean": 0.680132799995287, + "min": 0.5801970000029542, + "n": 30 + }, + "em-arg-where-as-string": { + "p50": 0.6473450000048615, + "p90": 0.7985450000269338, + "mean": 0.6849956333307394, + "min": 0.6061600000248291, + "n": 30 + }, + "em-arg-order-by-as-enum-literal": { + "p50": 0.6919929999858141, + "p90": 0.9983440000214614, + "mean": 0.8253625666664448, + "min": 0.6066930000088178, + "n": 30 + }, + "em-arg-order-by-as-string": { + "p50": 0.6934570000157692, + "p90": 0.8065460000070743, + "mean": 0.6997764999939439, + "min": 0.6173839999828488, + "n": 30 + }, + "em-arg-limit-as-object": { + "p50": 0.6731949999812059, + "p90": 0.7793599999858998, + "mean": 0.679954266672333, + "min": 0.5914209999609739, + "n": 30 + }, + "em-arg-limit-as-list": { + "p50": 0.6561199999996461, + "p90": 0.8267849999829195, + "mean": 0.6772978666684746, + "min": 0.5905900000361726, + "n": 30 + }, + "em-arg-distinct-on-unknown-column": { + "p50": 0.7561950000235811, + "p90": 1.078508000005968, + "mean": 1.7319832000066526, + "min": 0.5837890000548214, + "n": 30 + }, + "em-unknown-field-root-typo": { + "p50": 0.6075890000211075, + "p90": 0.8757329999934882, + "mean": 0.7214267666665061, + "min": 0.5596570000052452, + "n": 30 + }, + "em-unknown-field-object-rel": { + "p50": 0.7333730000536889, + "p90": 0.9352489999728277, + "mean": 0.7682150333382499, + "min": 0.67389799997909, + "n": 30 + }, + "em-unknown-field-array-rel": { + "p50": 0.8107250000466593, + "p90": 1.0040760000119917, + "mean": 0.8482870666659437, + "min": 0.7135049999924377, + "n": 30 + }, + "em-unknown-field-aggregate-wrapper": { + "p50": 0.7406169999740086, + "p90": 0.880723999987822, + "mean": 0.7484048999923592, + "min": 0.6191519999993034, + "n": 30 + }, + "em-unknown-field-aggregate-body": { + "p50": 0.8136099999537691, + "p90": 1.3489769999869168, + "mean": 1.0396718666578333, + "min": 0.6836009999969974, + "n": 30 + }, + "em-unknown-arg-aggregate-count": { + "p50": 0.7702019999851473, + "p90": 0.9084990000119433, + "mean": 0.7791908333388468, + "min": 0.6402760000200942, + "n": 30 + }, + "rm-agg-order-sum-desc-nulls-last": { + "p50": 252.45288400002755, + "p90": 269.631657000049, + "mean": 253.32531900002505, + "min": 243.09243499999866, + "n": 6 + }, + "rm-agg-order-min-asc-nulls-first": { + "p50": 255.26399999996647, + "p90": 264.00247200002195, + "mean": 256.080356833331, + "min": 251.7110630000243, + "n": 6 + }, + "em-unknown-arg-on-scalar-column": { + "p50": 0.714832000026945, + "p90": 0.8306180000072345, + "mean": 0.728872766677523, + "min": 0.6068629999645054, + "n": 30 + }, + "em-duplicate-argument-name": { + "p50": 0.4820130000007339, + "p90": 0.7099320000270382, + "mean": 0.5187814000004437, + "min": 0.3948530000052415, + "n": 30 + }, + "em-duplicate-key-in-input-object": { + "p50": 0.6397889999789186, + "p90": 0.8365600000252016, + "mean": 0.6305197999948481, + "min": 0.44083300000056624, + "n": 30 + }, + "em-duplicate-variable-definition": { + "p50": 0.7270290000014938, + "p90": 0.951589000003878, + "mean": 0.8924206666725998, + "min": 0.56165200000396, + "n": 30 + }, + "em-string-bad-unicode-escape": { + "p50": 0.5055580000043847, + "p90": 0.584249000006821, + "mean": 0.5087286000004193, + "min": 0.4140660000266507, + "n": 30 + }, + "em-string-lone-surrogate-escape": { + "p50": 0.4620569999678992, + "p90": 0.533326999982819, + "mean": 0.46315793333536326, + "min": 0.36756000004243106, + "n": 30 + }, + "em-string-unknown-escape": { + "p50": 0.5349799999967217, + "p90": 0.7156719999620691, + "mean": 0.5481422000021363, + "min": 0.39323400001740083, + "n": 30 + }, + "em-body-lone-surrogate-in-query": { + "p50": 0.3525969999609515, + "p90": 0.5708450000383891, + "mean": 0.5262488999966687, + "min": 0.29888499999651685, + "n": 30 + }, + "em-int-literal-overflow-int32": { + "p50": 0.603142999985721, + "p90": 0.7706550000002608, + "mean": 0.7230754666709497, + "min": 0.5527000000001863, + "n": 30 + }, + "em-int-literal-overflow-int64": { + "p50": 0.7155950000160374, + "p90": 0.8556400000234134, + "mean": 0.7297836666713313, + "min": 0.5702709999750368, + "n": 30 + }, + "em-float-literal-overflow": { + "p50": 0.7257259999751113, + "p90": 0.904411000024993, + "mean": 0.7571900666613752, + "min": 0.6317930000368506, + "n": 30 + }, + "em-var-string-decl-used-as-int": { + "p50": 0.7010080000036396, + "p90": 0.806860999960918, + "mean": 0.7013816333337066, + "min": 0.6142300000065006, + "n": 30 + }, + "em-var-wrong-name-used": { + "p50": 0.633166000014171, + "p90": 0.8100310000008903, + "mean": 0.6552637333360811, + "min": 0.5533319999813102, + "n": 30 + }, + "em-fragment-on-scalar-type": { + "p50": 1.3883619999978691, + "p90": 1.8286209999932908, + "mean": 2.380965366656892, + "min": 1.1154460000107065, + "n": 30 + }, + "em-fragment-on-enum-type": { + "p50": 1.3652180000208318, + "p90": 1.5026109999744222, + "mean": 1.3731600333354437, + "min": 1.243209999985993, + "n": 30 + }, + "em-inline-fragment-wrong-type": { + "p50": 1.36186699999962, + "p90": 1.4458689999883063, + "mean": 1.374538766668411, + "min": 1.277074999990873, + "n": 30 + }, + "em-directive-skip-on-query-operation": { + "p50": 0.7152839999762364, + "p90": 0.9377560000284575, + "mean": 0.8184067000033489, + "min": 0.6101980000385083, + "n": 30 + }, + "em-inline-fragment-unknown-type": { + "p50": 1.3598040000069886, + "p90": 1.480137000035029, + "mean": 1.380187533328232, + "min": 1.3006369999493472, + "n": 30 + }, + "em-by-pk-extra-unknown-arg": { + "p50": 0.7148499999893829, + "p90": 0.9152159999939613, + "mean": 0.7234675333330718, + "min": 0.5928570000105537, + "n": 30 + }, + "em-by-pk-id-null-literal": { + "p50": 0.7968949999776669, + "p90": 1.0483239999739453, + "mean": 0.9837571333317707, + "min": 0.6381779999937862, + "n": 30 + }, + "em-null-literal-limit": { + "p50": 1.4226739999721758, + "p90": 1.6211400000029244, + "mean": 1.4378825333318672, + "min": 1.1831290000118315, + "n": 30 + }, + "em-null-literal-where": { + "p50": 1.31501100002788, + "p90": 1.372016999986954, + "mean": 1.3263326000014786, + "min": 1.2525020000175573, + "n": 30 + }, + "em-empty-selection-braces-field": { + "p50": 0.6263069999986328, + "p90": 0.9710419999901205, + "mean": 0.722316100000171, + "min": 0.4991530000115745, + "n": 30 + }, + "em-empty-selection-braces-root": { + "p50": 0.6448629999649711, + "p90": 0.7890140000381507, + "mean": 0.6493170000011257, + "min": 0.5355729999719188, + "n": 30 + }, + "em-comments-only-query": { + "p50": 0.5455029999720864, + "p90": 0.7269269999815151, + "mean": 0.5853893333347514, + "min": 0.43328600004315376, + "n": 30 + }, + "em-whitespace-only-query": { + "p50": 0.6033790000365116, + "p90": 0.7393109999829903, + "mean": 0.6600274000064625, + "min": 0.4656010000035167, + "n": 30 + }, + "em-subscription-multiple-root-fields": { + "p50": 0.7509870000067167, + "p90": 0.8551699999952689, + "mean": 0.7621534999964449, + "min": 0.636088999977801, + "n": 30 + }, + "em-unknown-operation-type-keyword": { + "p50": 0.701885000045877, + "p90": 0.8700299999909475, + "mean": 0.7071354999963659, + "min": 0.5403439999790862, + "n": 30 + }, + "em-opname-empty-string": { + "p50": 0.5268829999840818, + "p90": 0.6441539999796078, + "mean": 0.5337411333360554, + "min": 0.40310600004158914, + "n": 30 + }, + "vr-typename-nested-everywhere": { + "p50": 1561.0384900000063, + "p90": 1696.9003169999924, + "mean": 1597.1129316666822, + "min": 1533.3999880000483, + "n": 3 + }, + "em-deep-nesting-40-levels": { + "p50": 5.259684999997262, + "p90": 37.64889399998356, + "mean": 8.71770986666476, + "min": 4.98277900001267, + "n": 30 + }, + "rm-order-object-rel-dangling-nulls-first": { + "p50": 687.9120390000171, + "p90": 737.4992339999881, + "mean": 702.1200073333263, + "min": 680.9487489999738, + "n": 3 + }, + "om-order-object-rel-nested-aggregate": { + "p50": 35650.71406899998, + "p90": 35871.03399200004, + "mean": 35705.062211666664, + "min": 35593.43857399997, + "n": 3 + }, + "wm-text-nin-empty": { + "p50": 1.2620929999975488, + "p90": 1.7026119999936782, + "mean": 2.1976722666663893, + "min": 1.1691629999986617, + "n": 30 + }, + "introspection-descriptions": { + "p50": 0.8383869999961462, + "p90": 1.0917429999972228, + "mean": 1.9213965666669537, + "min": 0.7551229999953648, + "n": 30 + }, + "introspection-descriptions-stream-cursor-value-input": { + "p50": 0.7950089999940246, + "p90": 0.9897579999960726, + "mean": 0.8216279999993276, + "min": 0.6737200000061421, + "n": 30 + }, + "introspection-descriptions-bool-exp-and-order-by": { + "p50": 1.1766139999963343, + "p90": 1.2721659999951953, + "mean": 1.1840921666667177, + "min": 1.0715740000014193, + "n": 30 + }, + "wm-jsonb-cast-string-like": { + "p50": 1.5186410000023898, + "p90": 1.7173580000089714, + "mean": 1.5159066333333613, + "min": 1.3042739999946207, + "n": 30 + }, + "wm-jsonb-cast-string-eq-scalar": { + "p50": 1.605794999995851, + "p90": 1.8482919999951264, + "mean": 1.6465377666662486, + "min": 1.4340620000002673, + "n": 30 + } + }, + "resources": [ + { + "label": "hasura", + "cpuSeconds": 39.8, + "peakRssMb": 734.54296875, + "avgRssMb": 312.5969620929912 + }, + { + "label": "postgres", + "cpuSeconds": 374.16, + "peakRssMb": 799.65625, + "avgRssMb": 540.0021902593819 + } + ] +} diff --git a/packages/e2e-tests/fixtures/differential/schema.sql b/packages/e2e-tests/fixtures/differential/schema.sql new file mode 100644 index 0000000000..795d19c91e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/schema.sql @@ -0,0 +1,524 @@ +-- Differential-suite fixture schema. +-- Generated from scenarios/test_codegen by `envio local db-migrate setup` + +-- pg_dump. Regenerate with: pnpm gen:differential-fixture +DROP SCHEMA IF EXISTS public CASCADE; +CREATE SCHEMA public; +GRANT ALL ON SCHEMA public TO public; +CREATE TYPE public.accounttype AS ENUM ( + 'ADMIN', + 'USER' +); +CREATE TYPE public.envio_history_change AS ENUM ( + 'SET', + 'DELETE' +); +CREATE TYPE public.gravatarsize AS ENUM ( + 'SMALL', + 'MEDIUM', + 'LARGE' +); +CREATE FUNCTION public.get_cache_row_count(table_name text) RETURNS integer + LANGUAGE plpgsql + AS $$ +DECLARE + result integer; +BEGIN + EXECUTE format('SELECT COUNT(*) FROM "public".%I', table_name) INTO result; + RETURN result; +END; +$$; +CREATE TABLE public."A" ( + id text NOT NULL, + b_id text NOT NULL, + "optionalStringToTestLinkedEntities" text +); +CREATE TABLE public."B" ( + id text NOT NULL, + c_id text +); +CREATE TABLE public."C" ( + id text NOT NULL, + a_id text NOT NULL, + "stringThatIsMirroredToA" text NOT NULL +); +CREATE TABLE public."CustomSelectionTestPass" ( + id text NOT NULL +); +CREATE TABLE public."D" ( + id text NOT NULL, + c text NOT NULL +); +CREATE TABLE public."EntityWith63LenghtName______________________________________one" ( + id text NOT NULL +); +CREATE TABLE public."EntityWith63LenghtName______________________________________two" ( + id text NOT NULL +); +CREATE TABLE public."EntityWithAllNonArrayTypes" ( + id text NOT NULL, + string text NOT NULL, + "optString" text, + int_ integer NOT NULL, + "optInt" integer, + float_ double precision NOT NULL, + "optFloat" double precision, + bool boolean NOT NULL, + "optBool" boolean, + "bigInt" numeric NOT NULL, + "optBigInt" numeric, + "bigDecimal" numeric NOT NULL, + "optBigDecimal" numeric, + "bigDecimalWithConfig" numeric(10,8) NOT NULL, + "enumField" public.accounttype NOT NULL, + "optEnumField" public.accounttype, + "timestamp" timestamp with time zone NOT NULL, + "optTimestamp" timestamp with time zone +); +CREATE TABLE public."EntityWithAllTypes" ( + id text NOT NULL, + string text NOT NULL, + "optString" text, + "arrayOfStrings" text[] NOT NULL, + int_ integer NOT NULL, + "optInt" integer, + "arrayOfInts" integer[] NOT NULL, + float_ double precision NOT NULL, + "optFloat" double precision, + "arrayOfFloats" double precision[] NOT NULL, + bool boolean NOT NULL, + "optBool" boolean, + "bigInt" numeric NOT NULL, + "optBigInt" numeric, + "arrayOfBigInts" text[] NOT NULL, + "bigDecimal" numeric NOT NULL, + "optBigDecimal" numeric, + "bigDecimalWithConfig" numeric(10,8) NOT NULL, + "arrayOfBigDecimals" text[] NOT NULL, + "timestamp" timestamp with time zone NOT NULL, + "optTimestamp" timestamp with time zone, + json jsonb NOT NULL, + "enumField" public.accounttype NOT NULL, + "optEnumField" public.accounttype +); +CREATE TABLE public."EntityWithBigDecimal" ( + id text NOT NULL, + "bigDecimal" numeric NOT NULL +); +CREATE TABLE public."EntityWithRestrictedReScriptField" ( + id text NOT NULL, + type text NOT NULL +); +CREATE TABLE public."EntityWithTimestamp" ( + id text NOT NULL, + "timestamp" timestamp with time zone NOT NULL +); +CREATE TABLE public."Gravatar" ( + id text NOT NULL, + owner_id text NOT NULL, + "displayName" text NOT NULL, + "imageUrl" text NOT NULL, + "updatesCount" numeric NOT NULL, + size public.gravatarsize NOT NULL +); +CREATE TABLE public."NftCollection" ( + id text NOT NULL, + "contractAddress" text NOT NULL, + name text NOT NULL, + symbol text NOT NULL, + "maxSupply" numeric NOT NULL, + "currentSupply" integer NOT NULL +); +CREATE TABLE public."PostgresNumericPrecisionEntityTester" ( + id text NOT NULL, + "exampleBigInt" numeric(76,0), + "exampleBigIntRequired" numeric(77,0) NOT NULL, + "exampleBigIntArray" numeric(78,0)[], + "exampleBigIntArrayRequired" numeric(79,0)[] NOT NULL, + "exampleBigDecimal" numeric(80,5), + "exampleBigDecimalRequired" numeric(81,5) NOT NULL, + "exampleBigDecimalArray" numeric(82,5)[], + "exampleBigDecimalArrayRequired" numeric(83,5)[] NOT NULL, + "exampleBigDecimalOtherOrder" numeric(84,6) NOT NULL +); +CREATE TABLE public."SimpleEntity" ( + id text NOT NULL, + value text NOT NULL +); +CREATE TABLE public."SimulateTestEvent" ( + id text NOT NULL, + "blockNumber" integer NOT NULL, + "logIndex" integer NOT NULL, + "timestamp" integer NOT NULL +); +CREATE TABLE public."Token" ( + id text NOT NULL, + "tokenId" numeric NOT NULL, + collection_id text NOT NULL, + owner_id text NOT NULL +); +CREATE TABLE public."User" ( + id text NOT NULL, + address text NOT NULL, + gravatar_id text, + "updatesCountOnUserForTesting" integer NOT NULL, + "accountType" public.accounttype NOT NULL +); +CREATE TABLE public.envio_chains ( + id integer NOT NULL, + start_block integer NOT NULL, + end_block integer, + max_reorg_depth integer NOT NULL, + buffer_block integer NOT NULL, + source_block integer NOT NULL, + first_event_block integer, + ready_at timestamp with time zone, + events_processed bigint NOT NULL, + _is_hyper_sync boolean NOT NULL, + progress_block integer NOT NULL +); +CREATE VIEW public._meta AS + SELECT id AS "chainId", + start_block AS "startBlock", + end_block AS "endBlock", + progress_block AS "progressBlock", + buffer_block AS "bufferBlock", + first_event_block AS "firstEventBlock", + (events_processed)::real AS "eventsProcessed", + source_block AS "sourceBlock", + ready_at AS "readyAt", + (ready_at IS NOT NULL) AS "isReady" + FROM public.envio_chains + ORDER BY id; +CREATE VIEW public.chain_metadata AS + SELECT source_block AS block_height, + id AS chain_id, + end_block, + first_event_block AS first_event_block_number, + _is_hyper_sync AS is_hyper_sync, + buffer_block AS latest_fetched_block_number, + progress_block AS latest_processed_block, + 0 AS num_batches_fetched, + (events_processed)::real AS num_events_processed, + start_block, + ready_at AS timestamp_caught_up_to_head_or_endblock + FROM public.envio_chains; +CREATE TABLE public.envio_addresses ( + id text NOT NULL, + chain_id integer NOT NULL, + registration_block integer NOT NULL, + registration_log_index integer NOT NULL, + contract_name text NOT NULL +); +CREATE TABLE public.envio_checkpoints ( + id bigint NOT NULL, + chain_id integer NOT NULL, + block_number integer NOT NULL, + block_hash text, + events_processed integer NOT NULL +); +CREATE TABLE public."envio_history_A" ( + id text NOT NULL, + b_id text, + "optionalStringToTestLinkedEntities" text, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_B" ( + id text NOT NULL, + c_id text, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_C" ( + id text NOT NULL, + a_id text, + "stringThatIsMirroredToA" text, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_CustomSelectionTestPass" ( + id text NOT NULL, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_D" ( + id text NOT NULL, + c text, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_EntityWith63LenghtName__________________________5" ( + id text NOT NULL, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_EntityWith63LenghtName__________________________6" ( + id text NOT NULL, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_EntityWithAllNonArrayTypes" ( + id text NOT NULL, + string text, + "optString" text, + int_ integer, + "optInt" integer, + float_ double precision, + "optFloat" double precision, + bool boolean, + "optBool" boolean, + "bigInt" numeric, + "optBigInt" numeric, + "bigDecimal" numeric, + "optBigDecimal" numeric, + "bigDecimalWithConfig" numeric(10,8), + "enumField" public.accounttype, + "optEnumField" public.accounttype, + "timestamp" timestamp with time zone, + "optTimestamp" timestamp with time zone, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_EntityWithAllTypes" ( + id text NOT NULL, + string text, + "optString" text, + "arrayOfStrings" text[], + int_ integer, + "optInt" integer, + "arrayOfInts" integer[], + float_ double precision, + "optFloat" double precision, + "arrayOfFloats" double precision[], + bool boolean, + "optBool" boolean, + "bigInt" numeric, + "optBigInt" numeric, + "arrayOfBigInts" text[], + "bigDecimal" numeric, + "optBigDecimal" numeric, + "bigDecimalWithConfig" numeric(10,8), + "arrayOfBigDecimals" text[], + "timestamp" timestamp with time zone, + "optTimestamp" timestamp with time zone, + json jsonb, + "enumField" public.accounttype, + "optEnumField" public.accounttype, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_EntityWithBigDecimal" ( + id text NOT NULL, + "bigDecimal" numeric, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_EntityWithRestrictedReScriptField" ( + id text NOT NULL, + type text, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_EntityWithTimestamp" ( + id text NOT NULL, + "timestamp" timestamp with time zone, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_Gravatar" ( + id text NOT NULL, + owner_id text, + "displayName" text, + "imageUrl" text, + "updatesCount" numeric, + size public.gravatarsize, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_NftCollection" ( + id text NOT NULL, + "contractAddress" text, + name text, + symbol text, + "maxSupply" numeric, + "currentSupply" integer, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_PostgresNumericPrecisionEntityTester" ( + id text NOT NULL, + "exampleBigInt" numeric(76,0), + "exampleBigIntRequired" numeric(77,0), + "exampleBigIntArray" numeric(78,0)[], + "exampleBigIntArrayRequired" numeric(79,0)[], + "exampleBigDecimal" numeric(80,5), + "exampleBigDecimalRequired" numeric(81,5), + "exampleBigDecimalArray" numeric(82,5)[], + "exampleBigDecimalArrayRequired" numeric(83,5)[], + "exampleBigDecimalOtherOrder" numeric(84,6), + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_SimpleEntity" ( + id text NOT NULL, + value text, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_SimulateTestEvent" ( + id text NOT NULL, + "blockNumber" integer, + "logIndex" integer, + "timestamp" integer, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_Token" ( + id text NOT NULL, + "tokenId" numeric, + collection_id text, + owner_id text, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public."envio_history_User" ( + id text NOT NULL, + address text, + gravatar_id text, + "updatesCountOnUserForTesting" integer, + "accountType" public.accounttype, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public.envio_history_envio_addresses ( + id text NOT NULL, + chain_id integer, + registration_block integer, + registration_log_index integer, + contract_name text, + envio_checkpoint_id bigint NOT NULL, + envio_change public.envio_history_change NOT NULL +); +CREATE TABLE public.envio_info ( + id integer DEFAULT 1 NOT NULL, + config text NOT NULL +); +CREATE TABLE public.raw_events ( + chain_id integer NOT NULL, + event_id bigint NOT NULL, + event_name text NOT NULL, + contract_name text NOT NULL, + block_number integer NOT NULL, + log_index integer NOT NULL, + src_address text NOT NULL, + block_hash text NOT NULL, + block_timestamp integer NOT NULL, + block_fields jsonb NOT NULL, + transaction_fields jsonb NOT NULL, + params jsonb NOT NULL, + serial bigint NOT NULL +); +CREATE SEQUENCE public.raw_events_serial_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; +ALTER SEQUENCE public.raw_events_serial_seq OWNED BY public.raw_events.serial; +ALTER TABLE ONLY public.raw_events ALTER COLUMN serial SET DEFAULT nextval('public.raw_events_serial_seq'::regclass); +ALTER TABLE ONLY public."A" + ADD CONSTRAINT "A_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."B" + ADD CONSTRAINT "B_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."C" + ADD CONSTRAINT "C_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."CustomSelectionTestPass" + ADD CONSTRAINT "CustomSelectionTestPass_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."D" + ADD CONSTRAINT "D_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."EntityWith63LenghtName______________________________________one" + ADD CONSTRAINT "EntityWith63LenghtName_____________________________________pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."EntityWith63LenghtName______________________________________two" + ADD CONSTRAINT "EntityWith63LenghtName____________________________________pkey1" PRIMARY KEY (id); +ALTER TABLE ONLY public."EntityWithAllNonArrayTypes" + ADD CONSTRAINT "EntityWithAllNonArrayTypes_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."EntityWithAllTypes" + ADD CONSTRAINT "EntityWithAllTypes_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."EntityWithBigDecimal" + ADD CONSTRAINT "EntityWithBigDecimal_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."EntityWithRestrictedReScriptField" + ADD CONSTRAINT "EntityWithRestrictedReScriptField_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."EntityWithTimestamp" + ADD CONSTRAINT "EntityWithTimestamp_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."Gravatar" + ADD CONSTRAINT "Gravatar_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."NftCollection" + ADD CONSTRAINT "NftCollection_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."PostgresNumericPrecisionEntityTester" + ADD CONSTRAINT "PostgresNumericPrecisionEntityTester_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."SimpleEntity" + ADD CONSTRAINT "SimpleEntity_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."SimulateTestEvent" + ADD CONSTRAINT "SimulateTestEvent_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."Token" + ADD CONSTRAINT "Token_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public."User" + ADD CONSTRAINT "User_pkey" PRIMARY KEY (id); +ALTER TABLE ONLY public.envio_addresses + ADD CONSTRAINT envio_addresses_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public.envio_chains + ADD CONSTRAINT envio_chains_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public.envio_checkpoints + ADD CONSTRAINT envio_checkpoints_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public."envio_history_A" + ADD CONSTRAINT "envio_history_A_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_B" + ADD CONSTRAINT "envio_history_B_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_C" + ADD CONSTRAINT "envio_history_C_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_CustomSelectionTestPass" + ADD CONSTRAINT "envio_history_CustomSelectionTestPass_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_D" + ADD CONSTRAINT "envio_history_D_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_EntityWith63LenghtName__________________________5" + ADD CONSTRAINT "envio_history_EntityWith63LenghtName_______________________pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_EntityWith63LenghtName__________________________6" + ADD CONSTRAINT "envio_history_EntityWith63LenghtName______________________pkey1" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_EntityWithAllNonArrayTypes" + ADD CONSTRAINT "envio_history_EntityWithAllNonArrayTypes_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_EntityWithAllTypes" + ADD CONSTRAINT "envio_history_EntityWithAllTypes_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_EntityWithBigDecimal" + ADD CONSTRAINT "envio_history_EntityWithBigDecimal_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_EntityWithRestrictedReScriptField" + ADD CONSTRAINT "envio_history_EntityWithRestrictedReScriptField_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_EntityWithTimestamp" + ADD CONSTRAINT "envio_history_EntityWithTimestamp_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_Gravatar" + ADD CONSTRAINT "envio_history_Gravatar_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_NftCollection" + ADD CONSTRAINT "envio_history_NftCollection_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_PostgresNumericPrecisionEntityTester" + ADD CONSTRAINT "envio_history_PostgresNumericPrecisionEntityTester_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_SimpleEntity" + ADD CONSTRAINT "envio_history_SimpleEntity_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_SimulateTestEvent" + ADD CONSTRAINT "envio_history_SimulateTestEvent_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_Token" + ADD CONSTRAINT "envio_history_Token_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public."envio_history_User" + ADD CONSTRAINT "envio_history_User_pkey" PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public.envio_history_envio_addresses + ADD CONSTRAINT envio_history_envio_addresses_pkey PRIMARY KEY (id, envio_checkpoint_id); +ALTER TABLE ONLY public.envio_info + ADD CONSTRAINT envio_info_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public.raw_events + ADD CONSTRAINT raw_events_pkey PRIMARY KEY (serial); +CREATE INDEX "A_b_id" ON public."A" USING btree (b_id); +CREATE INDEX "D_c" ON public."D" USING btree (c); +CREATE INDEX "Token_collection_id" ON public."Token" USING btree (collection_id); +CREATE INDEX "Token_id_tokenId" ON public."Token" USING btree (id, "tokenId"); +CREATE INDEX "Token_owner_id" ON public."Token" USING btree (owner_id); +CREATE INDEX "Token_tokenId" ON public."Token" USING btree ("tokenId"); +CREATE INDEX "Token_tokenId_collection_id" ON public."Token" USING btree ("tokenId", collection_id); +CREATE INDEX "Token_tokenId_desc_owner_id" ON public."Token" USING btree ("tokenId" DESC, owner_id); diff --git a/packages/e2e-tests/fixtures/differential/seed.sql b/packages/e2e-tests/fixtures/differential/seed.sql new file mode 100644 index 0000000000..c349fc8034 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/seed.sql @@ -0,0 +1,148 @@ +-- Deterministic seed for the differential GraphQL suite. +-- Values are chosen to exercise serialization edge cases: unicode, quoting, +-- numeric extremes, Infinity/NaN floats, timestamp precision, jsonb variants, +-- dangling relationship references, and empty arrays. + +INSERT INTO public."NftCollection" (id, "contractAddress", name, symbol, "maxSupply", "currentSupply") VALUES +('coll-1', '0x1111111111111111111111111111111111111111', 'Alpha Apes', 'ALPHA', 10000, 3), +('coll-2', '0x2222222222222222222222222222222222222222', 'Béta Bots 🤖', 'BÉTA', 340282366920938463463374607431768211455, 5), +('coll-3', '0x3333333333333333333333333333333333333333', '', '', 0, 0); + +INSERT INTO public."User" (id, address, gravatar_id, "updatesCountOnUserForTesting", "accountType") VALUES +('user-1', '0xaaaa000000000000000000000000000000000001', 'grav-1', 0, 'ADMIN'), +('user-2', '0xaaaa000000000000000000000000000000000002', 'grav-2', 42, 'USER'), +('user-3', '0xaaaa000000000000000000000000000000000003', NULL, 2147483647, 'USER'), +('user-4', '0xaaaa000000000000000000000000000000000004', NULL, -2147483648, 'ADMIN'), +('user "quoted" 🚀', '0xaaaa000000000000000000000000000000000005', NULL, 5, 'USER'), +('user-dangling', '0xaaaa000000000000000000000000000000000006', 'grav-missing', 7, 'USER'); + +INSERT INTO public."Gravatar" (id, owner_id, "displayName", "imageUrl", "updatesCount", size) VALUES +('grav-1', 'user-1', 'First Grav', 'https://example.com/1.png', 3, 'SMALL'), +('grav-2', 'user-2', 'Zwölf Grüße 中文', 'https://example.com/ü.png', 99999999999999999999999999999999999999, 'MEDIUM'), +('grav-3', 'user-missing', 'Dangling owner', 'https://example.com/3.png', 0, 'LARGE'); + +INSERT INTO public."Token" (id, "tokenId", collection_id, owner_id) VALUES +('tok-1', 0, 'coll-1', 'user-1'), +('tok-2', 1, 'coll-1', 'user-1'), +('tok-3', 2, 'coll-1', 'user-2'), +('tok-4', 1000000000000000000000000000000, 'coll-2', 'user-2'), +('tok-5', -5, 'coll-2', 'user-3'), +('tok-6', 123456789, 'coll-2', 'user-missing'), +('tok-7', 7, 'coll-missing', 'user-1'), +('tok-8', 8, 'coll-2', 'user "quoted" 🚀'), +('tok-9', 9999999999999999999999999999999999999999999999999999999999999999999999999999, 'coll-2', 'user-4'), +('tok-10', 10, 'coll-1', 'user-4'); + +INSERT INTO public."B" (id, c_id) VALUES +('b-1', 'c-1'), +('b-2', NULL), +('b-3', 'c-missing'); + +INSERT INTO public."A" (id, b_id, "optionalStringToTestLinkedEntities") VALUES +('a-1', 'b-1', 'linked'), +('a-2', 'b-1', NULL), +('a-3', 'b-2', ''), +('a-4', 'b-missing', 'dangling b'); + +INSERT INTO public."C" (id, a_id, "stringThatIsMirroredToA") VALUES +('c-1', 'a-1', 'mirror-1'), +('c-2', 'a-2', 'mirror-2'); + +INSERT INTO public."D" (id, c) VALUES +('d-1', 'c-1'), +('d-2', 'c-1'), +('d-3', 'c-2'), +('d-4', 'c-missing'); + +INSERT INTO public."EntityWithAllNonArrayTypes" +(id, string, "optString", int_, "optInt", float_, "optFloat", bool, "optBool", "bigInt", "optBigInt", "bigDecimal", "optBigDecimal", "bigDecimalWithConfig", "enumField", "optEnumField", timestamp, "optTimestamp") VALUES +('scalar-1', 'plain', 'present', 1, 10, 1.5, 2.5, true, true, 100, 200, 1.25, 3.75, 1.00000001, 'ADMIN', 'USER', '2024-01-15T12:34:56.789+00', '2024-01-15T12:34:56.789123+00'), +('scalar-nulls', 'has nulls', NULL, 0, NULL, 0, NULL, false, NULL, 0, NULL, 0, NULL, 0, 'USER', NULL, '1970-01-01T00:00:00+00', NULL), +('scalar-extremes', 'extremes', 'x', 2147483647, -2147483648, 1.7976931348623157e308, 5e-324, true, false, 9999999999999999999999999999999999999999999999999999999999999999999999999999, -9999999999999999999999999999999999999999999999999999999999999999999999999999, 12345678901234567890.123456789, -0.000000001, 99.99999999, 'ADMIN', 'ADMIN', '9999-12-31T23:59:59.999999+00', '1969-12-31T23:59:59.999999+00'), +('scalar-special-float', 'inf and nan', NULL, -1, NULL, 'Infinity', 'NaN', false, NULL, 1, NULL, 1.1000, NULL, 0.5, 'USER', NULL, '2000-02-29T00:00:00+00', NULL), +('scalar-neg-inf', 'neg inf', NULL, -2, NULL, '-Infinity', '-0', true, NULL, -1, NULL, -1.5, NULL, -0.00000001, 'USER', NULL, '2024-06-30T23:59:60+00', NULL), +('scalar-unicode', 'héllo wörld 中文测试 🚀🎉', 'emoji 🤖', 7, 7, -3.14159, 2.718281828459045, true, true, 42, -42, 3.14000, 0.00000, 2.50000000, 'USER', 'USER', '2024-12-25T18:30:00+05:30', '2024-12-25T18:30:00-08:00'), +('scalar-quotes', E'with "double" and \'single\' and back\\slash and\nnewline and\ttab', 'end', 3, 3, 0.1, 0.2, false, false, 7, 8, 0.5, 0.5, 3.00000000, 'ADMIN', 'USER', '2024-03-10T10:00:00+00', '2024-03-10T10:00:00+00'), +('scalar-empty', '', '', 4, 0, -0.5, 0, true, false, 10, 0, 100, 0, 0.00000001, 'USER', 'ADMIN', '2024-07-04T00:00:00.1+00', '2024-07-04T00:00:00.12+00'); + +INSERT INTO public."EntityWithAllTypes" +(id, string, "optString", "arrayOfStrings", int_, "optInt", "arrayOfInts", float_, "optFloat", "arrayOfFloats", bool, "optBool", "bigInt", "optBigInt", "arrayOfBigInts", "bigDecimal", "optBigDecimal", "bigDecimalWithConfig", "arrayOfBigDecimals", timestamp, "optTimestamp", json, "enumField", "optEnumField") VALUES +('all-1', 'first', 'opt', '{"one","two","three"}', 1, 2, '{1,2,3}', 1.5, 2.5, '{1.5,2.5,-3.5}', true, false, 1000, 2000, '{"1","2","3"}', 10.5, 20.5, 1.12345678, '{"1.5","2.25"}', '2024-01-01T00:00:00+00', '2024-01-02T00:00:00+00', '{"kind": "object", "n": 1, "nested": {"a": [1, 2]}}', 'ADMIN', 'USER'), +('all-empty-arrays', 'empty', NULL, '{}', 0, NULL, '{}', 0, NULL, '{}', false, NULL, 0, NULL, '{}', 0, NULL, 0, '{}', '2024-01-01T00:00:00+00', NULL, '{}', 'USER', NULL), +('all-array-edge', 'array edges', 'x', '{"with,comma","with}brace","with\"quote","with''single",""," leading space","emoji 🚀","back\\slash"}', -1, -2, '{-2147483648,0,2147483647}', -1.5, NULL, '{0,-0.5}', true, true, -1, 1, '{"-99999999999999999999999999999999999999","0","99999999999999999999999999999999999999"}', -0.5, 0.5, -1.00000001, '{"-1.5","0.0","1.500"}', '2024-05-05T05:05:05.55555+00', '2024-05-05T05:05:05.555555+00', '[1, "two", null, true, {"k": "v"}, [2.5]]', 'ADMIN', 'ADMIN'), +('all-json-string', 'json scalar string', NULL, '{"a"}', 5, 5, '{5}', 5.5, 5.5, '{5.5}', true, NULL, 5, 5, '{"5"}', 5.5, 5.5, 5.00000000, '{"5.5"}', '2024-02-02T02:02:02+00', NULL, '"just a string"', 'USER', NULL), +('all-json-number', 'json scalar number', NULL, '{"b"}', 6, NULL, '{6}', 6.5, NULL, '{6.5}', false, NULL, 6, NULL, '{"6"}', 6.5, NULL, 6.00000000, '{"6.5"}', '2024-02-03T02:02:02+00', NULL, '123456789012345678901234567890.5', 'USER', NULL), +('all-json-null', 'jsonb null literal', NULL, '{"c"}', 7, NULL, '{7}', 7.5, NULL, '{7.5}', true, NULL, 7, NULL, '{"7"}', 7.5, NULL, 7.00000000, '{"7.5"}', '2024-02-04T02:02:02+00', NULL, 'null', 'ADMIN', NULL), +('all-json-unicode', 'json unicode', NULL, '{"d"}', 8, NULL, '{8}', 8.5, NULL, '{8.5}', false, NULL, 8, NULL, '{"8"}', 8.5, NULL, 8.00000000, '{"8.5"}', '2024-02-05T02:02:02+00', NULL, '{"héllo": "wörld 🚀", "esc": "a\"b\\c\nd", "num": 1e100}', 'USER', NULL), +('all-json-bool', 'json scalar bool', NULL, '{"e"}', 9, NULL, '{9}', 9.5, NULL, '{9.5}', true, NULL, 9, NULL, '{"9"}', 9.5, NULL, 9.00000000, '{"9.5"}', '2024-02-06T02:02:02+00', NULL, 'false', 'USER', NULL); + +INSERT INTO public."PostgresNumericPrecisionEntityTester" +(id, "exampleBigInt", "exampleBigIntRequired", "exampleBigIntArray", "exampleBigIntArrayRequired", "exampleBigDecimal", "exampleBigDecimalRequired", "exampleBigDecimalArray", "exampleBigDecimalArrayRequired", "exampleBigDecimalOtherOrder") VALUES +('prec-1', + 9999999999999999999999999999999999999999999999999999999999999999999999999999, + 99999999999999999999999999999999999999999999999999999999999999999999999999999, + '{1,2,3}', + '{-1,-2,-3}', + 123456789012345678901234567890123456789012345678901234567890123456789012345.12345, + -123456789012345678901234567890123456789012345678901234567890123456789012345.54321, + '{0.00001,-0.00001}', + '{123.45678}', + 0.123456), +('prec-nulls', NULL, 0, NULL, '{}', NULL, 0, NULL, '{}', 0), +('prec-2', -1, 1, '{0}', '{9999999999}', 1.5, -1.5, '{1.10000}', '{-1.10000}', -0.000001); + +INSERT INTO public."EntityWithBigDecimal" (id, "bigDecimal") VALUES +('bd-1', 0), +('bd-2', 1.10), +('bd-3', -1.10), +('bd-4', 123456789.123456789), +('bd-5', 0.000000000000000001); + +INSERT INTO public."EntityWithTimestamp" (id, timestamp) VALUES +('ts-epoch', '1970-01-01T00:00:00+00'), +('ts-micro', '2024-01-15T12:34:56.123456+00'), +('ts-milli', '2024-01-15T12:34:56.123+00'), +('ts-pre-epoch', '1969-07-20T20:17:40+00'), +('ts-future', '9999-12-31T23:59:59.999999+00'), +('ts-zoned', '2024-06-15T12:00:00+09:30'); + +INSERT INTO public."EntityWithRestrictedReScriptField" (id, type) VALUES +('restricted-1', 'the type field'), +('restricted-2', ''); + +INSERT INTO public."SimpleEntity" (id, value) VALUES +('simple-1', 'v1'), +('simple-2', 'v2'), +('simple-3', 'v3'), +('simple-4', 'v4'), +('simple-5', 'v5'), +('simple-6', 'v6'), +('simple-7', 'v7'), +('simple-8', 'v8'), +('simple-9', 'v9'), +('simple-10', 'v10'); + +INSERT INTO public."SimulateTestEvent" (id, "blockNumber", "logIndex", timestamp) VALUES +('sim-1', 100, 0, 1700000000), +('sim-2', 100, 1, 1700000000), +('sim-3', 101, 0, 1700000012), +('sim-4', 102, 5, 1700000024), +('sim-5', 103, 2, 1700000036); + +INSERT INTO public."CustomSelectionTestPass" (id) VALUES ('custom-1'), ('custom-2'); + +INSERT INTO public."EntityWith63LenghtName______________________________________one" (id) VALUES ('long-1'), ('long-2'); +INSERT INTO public."EntityWith63LenghtName______________________________________two" (id) VALUES ('long-1'); + +INSERT INTO public.raw_events +(chain_id, event_id, event_name, contract_name, block_number, log_index, src_address, block_hash, block_timestamp, block_fields, transaction_fields, params) VALUES +(1, 4611686018427387904, 'Transfer', 'Gravatar', 10861674, 0, '0x2b2f78c5bf6d9c12ee1225d5f374aa91204580c3', '0xblock1', 1600000000, '{"number": 10861674}', '{"hash": "0xtx1", "transactionIndex": 0}', '{"from": "0x0", "to": "0x1", "value": "100"}'), +(1, 4611686018427387905, 'Transfer', 'Gravatar', 10861674, 1, '0x2b2f78c5bf6d9c12ee1225d5f374aa91204580c3', '0xblock1', 1600000000, '{"number": 10861674}', '{"hash": "0xtx1", "transactionIndex": 0}', '{"from": "0x1", "to": "0x2", "value": "9999999999999999999999999999"}'), +(1, 4611686018427387906, 'NewGravatar', 'Gravatar', 10861675, 0, '0x2b2f78c5bf6d9c12ee1225d5f374aa91204580c3', '0xblock2', 1600000012, '{"number": 10861675}', '{}', '{"id": "1", "displayName": "unicode 🚀", "nested": {"deep": [1, null, "x"]}}'), +(1337, 1, 'EmptyEvent', 'Noop', 1, 0, '0x0000000000000000000000000000000000000000', '0xblockA', 1500000000, '{}', '{}', '{}'), +(1337, 2, 'FilterTestEvent', 'EventFiltersTest', 2, 3, '0x4444444444444444444444444444444444444444', '0xblockB', 1500000060, '{"number": 2, "extra": true}', '{"hash": null}', '{"addr": "0x5555555555555555555555555555555555555555"}'); + +INSERT INTO public.envio_chains +(id, start_block, end_block, max_reorg_depth, buffer_block, source_block, first_event_block, ready_at, events_processed, _is_hyper_sync, progress_block) VALUES +(1, 0, NULL, 200, 10861774, 10861800, 10861674, '2024-11-01T10:20:30.456+00', 2147487821, true, 10861774), +(1337, 1, 5000, 0, 4000, 4500, NULL, NULL, 0, false, 3999); diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-aliases.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-aliases.json new file mode 100644 index 0000000000..8180278deb --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-aliases.json @@ -0,0 +1,21 @@ +{ + "role": "admin", + "request": { + "query": "{ total: User_aggregate { aggregate { c: count } } admins: User_aggregate(where: {accountType: {_eq: \"ADMIN\"}}) { aggregate { count } } }" + }, + "status": 200, + "body": { + "data": { + "total": { + "aggregate": { + "c": 6 + } + }, + "admins": { + "aggregate": { + "count": 2 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-basic.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-basic.json new file mode 100644 index 0000000000..8c46c0aa73 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-basic.json @@ -0,0 +1,16 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { count } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "count": 6 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-column.json new file mode 100644 index 0000000000..c8ec187d4e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-column.json @@ -0,0 +1,16 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { count(columns: gravatar_id) } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "count": 3 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-distinct-false.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-distinct-false.json new file mode 100644 index 0000000000..c1ead3e481 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-distinct-false.json @@ -0,0 +1,16 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { count(columns: owner_id, distinct: false) } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 10 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-distinct.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-distinct.json new file mode 100644 index 0000000000..b29ea1eaf6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-distinct.json @@ -0,0 +1,16 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { count(columns: owner_id, distinct: true) } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 6 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-with-where.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-with-where.json new file mode 100644 index 0000000000..6353405b06 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-count-with-where.json @@ -0,0 +1,16 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate(where: {accountType: {_eq: \"ADMIN\"}}) { aggregate { count } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "count": 2 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-empty-set.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-empty-set.json new file mode 100644 index 0000000000..512c27bca8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-empty-set.json @@ -0,0 +1,28 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate(where: {id: {_eq: \"missing\"}}) { aggregate { count sum { updatesCountOnUserForTesting } avg { updatesCountOnUserForTesting } min { id } max { id } } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "count": 0, + "sum": { + "updatesCountOnUserForTesting": null + }, + "avg": { + "updatesCountOnUserForTesting": null + }, + "min": { + "id": null + }, + "max": { + "id": null + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-int.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-int.json new file mode 100644 index 0000000000..40f4032d2c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-int.json @@ -0,0 +1,21 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { min { updatesCountOnUserForTesting } max { updatesCountOnUserForTesting } } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "min": { + "updatesCountOnUserForTesting": -2147483648 + }, + "max": { + "updatesCountOnUserForTesting": 2147483647 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-numeric.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-numeric.json new file mode 100644 index 0000000000..a045025cd2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-numeric.json @@ -0,0 +1,21 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { min { tokenId } max { tokenId } } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "min": { + "tokenId": "-5" + }, + "max": { + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-string.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-string.json new file mode 100644 index 0000000000..eba78281a5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-string.json @@ -0,0 +1,23 @@ +{ + "role": "admin", + "request": { + "query": "{ SimpleEntity_aggregate { aggregate { min { id value } max { id value } } } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity_aggregate": { + "aggregate": { + "min": { + "id": "simple-1", + "value": "v1" + }, + "max": { + "id": "simple-9", + "value": "v9" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-timestamp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-timestamp.json new file mode 100644 index 0000000000..7c67cc65bc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-min-max-timestamp.json @@ -0,0 +1,21 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithTimestamp_aggregate { aggregate { min { timestamp } max { timestamp } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp_aggregate": { + "aggregate": { + "min": { + "timestamp": "1969-07-20T20:17:40+00:00" + }, + "max": { + "timestamp": "9999-12-31T23:59:59.999999+00:00" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nested-array-relationship.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nested-array-relationship.json new file mode 100644 index 0000000000..d11e2e2687 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nested-array-relationship.json @@ -0,0 +1,79 @@ +{ + "role": "admin", + "request": { + "query": "{ User(order_by: {id: asc}) { id tokens_aggregate { aggregate { count sum { tokenId } } } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "tokens_aggregate": { + "aggregate": { + "count": 1, + "sum": { + "tokenId": "8" + } + } + } + }, + { + "id": "user-1", + "tokens_aggregate": { + "aggregate": { + "count": 3, + "sum": { + "tokenId": "8" + } + } + } + }, + { + "id": "user-2", + "tokens_aggregate": { + "aggregate": { + "count": 2, + "sum": { + "tokenId": "1000000000000000000000000000002" + } + } + } + }, + { + "id": "user-3", + "tokens_aggregate": { + "aggregate": { + "count": 1, + "sum": { + "tokenId": "-5" + } + } + } + }, + { + "id": "user-4", + "tokens_aggregate": { + "aggregate": { + "count": 2, + "sum": { + "tokenId": "10000000000000000000000000000000000000000000000000000000000000000000000000009" + } + } + } + }, + { + "id": "user-dangling", + "tokens_aggregate": { + "aggregate": { + "count": 0, + "sum": { + "tokenId": null + } + } + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nested-public-role-denied.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nested-public-role-denied.json new file mode 100644 index 0000000000..df04e43577 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nested-public-role-denied.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 1) { id tokens_aggregate { aggregate { count } } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'tokens_aggregate' not found in type: 'User'", + "extensions": { + "path": "$.selectionSet.User.selectionSet.tokens_aggregate", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nested-with-args.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nested-with-args.json new file mode 100644 index 0000000000..5d110059cc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nested-with-args.json @@ -0,0 +1,72 @@ +{ + "role": "admin", + "request": { + "query": "{ NftCollection(order_by: {id: asc}) { id tokens_aggregate(where: {tokenId: {_gte: 1}}, order_by: {tokenId: asc}) { aggregate { count max { tokenId } } nodes { id } } } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-1", + "tokens_aggregate": { + "aggregate": { + "count": 3, + "max": { + "tokenId": "10" + } + }, + "nodes": [ + { + "id": "tok-2" + }, + { + "id": "tok-3" + }, + { + "id": "tok-10" + } + ] + } + }, + { + "id": "coll-2", + "tokens_aggregate": { + "aggregate": { + "count": 4, + "max": { + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + }, + "nodes": [ + { + "id": "tok-8" + }, + { + "id": "tok-6" + }, + { + "id": "tok-4" + }, + { + "id": "tok-9" + } + ] + } + }, + { + "id": "coll-3", + "tokens_aggregate": { + "aggregate": { + "count": 0, + "max": { + "tokenId": null + } + }, + "nodes": [] + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nodes-only.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nodes-only.json new file mode 100644 index 0000000000..447d325098 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nodes-only.json @@ -0,0 +1,21 @@ +{ + "role": "admin", + "request": { + "query": "{ SimpleEntity_aggregate(order_by: {id: desc}, limit: 2) { nodes { id } } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity_aggregate": { + "nodes": [ + { + "id": "simple-9" + }, + { + "id": "simple-8" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nodes.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nodes.json new file mode 100644 index 0000000000..b49a6fc282 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-nodes.json @@ -0,0 +1,30 @@ +{ + "role": "admin", + "request": { + "query": "{ SimpleEntity_aggregate(order_by: {id: asc}, limit: 3) { aggregate { count } nodes { id value } } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity_aggregate": { + "aggregate": { + "count": 3 + }, + "nodes": [ + { + "id": "simple-1", + "value": "v1" + }, + { + "id": "simple-10", + "value": "v10" + }, + { + "id": "simple-2", + "value": "v2" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-public-role-denied.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-public-role-denied.json new file mode 100644 index 0000000000..1d82d0a32a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-public-role-denied.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_aggregate { aggregate { count } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'User_aggregate' not found in type: 'query_root'", + "extensions": { + "path": "$.selectionSet.User_aggregate", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-stddev-variance.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-stddev-variance.json new file mode 100644 index 0000000000..6668d312f8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-stddev-variance.json @@ -0,0 +1,33 @@ +{ + "role": "admin", + "request": { + "query": "{ SimulateTestEvent_aggregate { aggregate { stddev { blockNumber } stddev_pop { blockNumber } stddev_samp { blockNumber } variance { blockNumber } var_pop { blockNumber } var_samp { blockNumber } } } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent_aggregate": { + "aggregate": { + "stddev": { + "blockNumber": 1.3038404810405297 + }, + "stddev_pop": { + "blockNumber": 1.1661903789690602 + }, + "stddev_samp": { + "blockNumber": 1.3038404810405297 + }, + "variance": { + "blockNumber": 1.7 + }, + "var_pop": { + "blockNumber": 1.36 + }, + "var_samp": { + "blockNumber": 1.7 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-sum-avg-int-float.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-sum-avg-int-float.json new file mode 100644 index 0000000000..e54df06217 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-sum-avg-int-float.json @@ -0,0 +1,25 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate(where: {id: {_in: [\"scalar-1\", \"scalar-nulls\", \"scalar-empty\"]}}) { aggregate { sum { int_ float_ bigInt bigDecimal } avg { int_ float_ } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "sum": { + "int_": 5, + "float_": "1", + "bigInt": "110", + "bigDecimal": "101.25" + }, + "avg": { + "int_": 1.6666666666666667, + "float_": "0.3333333333333333" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-sum-avg-numeric.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-sum-avg-numeric.json new file mode 100644 index 0000000000..1dca140914 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-sum-avg-numeric.json @@ -0,0 +1,21 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { sum { tokenId } avg { tokenId } } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "sum": { + "tokenId": "10000000000000000000000000000000000000000000001000000000000000000000123456811" + }, + "avg": { + "tokenId": "1000000000000000000000000000000000000000000000100000000000000000000012345681" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-typename.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-typename.json new file mode 100644 index 0000000000..4014b92bb8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-typename.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { __typename aggregate { __typename count } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "__typename": "User_aggregate", + "aggregate": { + "__typename": "User_aggregate_fields", + "count": 6 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-with-distinct-on.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-with-distinct-on.json new file mode 100644 index 0000000000..d936ad7732 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-with-distinct-on.json @@ -0,0 +1,42 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate(distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}]) { aggregate { count } nodes { id owner_id } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 6 + }, + "nodes": [ + { + "id": "tok-8", + "owner_id": "user \"quoted\" 🚀" + }, + { + "id": "tok-7", + "owner_id": "user-1" + }, + { + "id": "tok-4", + "owner_id": "user-2" + }, + { + "id": "tok-5", + "owner_id": "user-3" + }, + { + "id": "tok-9", + "owner_id": "user-4" + }, + { + "id": "tok-6", + "owner_id": "user-missing" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/agg-with-limit-offset.json b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-with-limit-offset.json new file mode 100644 index 0000000000..8c220087b0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/agg-with-limit-offset.json @@ -0,0 +1,30 @@ +{ + "role": "admin", + "request": { + "query": "{ SimpleEntity_aggregate(order_by: {id: asc}, limit: 4, offset: 2) { aggregate { count } nodes { id } } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity_aggregate": { + "aggregate": { + "count": 4 + }, + "nodes": [ + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-agg-variables-where.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-agg-variables-where.json new file mode 100644 index 0000000000..86c360779d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-agg-variables-where.json @@ -0,0 +1,26 @@ +{ + "role": "admin", + "request": { + "query": "query ($w: Token_bool_exp) { Token_aggregate(where: $w) { aggregate { count sum { tokenId } } } }", + "variables": { + "w": { + "collection_id": { + "_eq": "coll-1" + } + } + } + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 4, + "sum": { + "tokenId": "13" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-chainmeta-float4-matrix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-chainmeta-float4-matrix.json new file mode 100644 index 0000000000..c16a8be11c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-chainmeta-float4-matrix.json @@ -0,0 +1,28 @@ +{ + "role": "admin", + "request": { + "query": "{ chain_metadata_aggregate { aggregate { count sum { num_events_processed } avg { num_events_processed } min { num_events_processed } max { num_events_processed } } } }" + }, + "status": 200, + "body": { + "data": { + "chain_metadata_aggregate": { + "aggregate": { + "count": 2, + "sum": { + "num_events_processed": 2147487700 + }, + "avg": { + "num_events_processed": 1073743872 + }, + "min": { + "num_events_processed": 0 + }, + "max": { + "num_events_processed": 2147487700 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-distinct-no-columns.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-distinct-no-columns.json new file mode 100644 index 0000000000..b544067a72 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-distinct-no-columns.json @@ -0,0 +1,16 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { count(distinct: true) } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "count": 6 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-distinct-no-nulls.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-distinct-no-nulls.json new file mode 100644 index 0000000000..e06889bc09 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-distinct-no-nulls.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { total: count all: count(columns: owner_id) dist: count(columns: owner_id, distinct: true) } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "total": 10, + "all": 10, + "dist": 6 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-distinct-with-nulls.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-distinct-with-nulls.json new file mode 100644 index 0000000000..80e3287ef1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-distinct-with-nulls.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { total: count all: count(columns: gravatar_id) dist: count(columns: gravatar_id, distinct: true) } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "total": 6, + "all": 3, + "dist": 3 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-multi-columns-distinct.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-multi-columns-distinct.json new file mode 100644 index 0000000000..da4430215e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-multi-columns-distinct.json @@ -0,0 +1,16 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { count(columns: [owner_id, collection_id], distinct: true) } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 9 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-multi-columns.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-multi-columns.json new file mode 100644 index 0000000000..8878876229 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-count-multi-columns.json @@ -0,0 +1,16 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { count(columns: [gravatar_id, accountType]) } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "count": 6 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-count-variants.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-count-variants.json new file mode 100644 index 0000000000..663f8ea4de --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-count-variants.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate(where: {id: {_eq: \"missing\"}}) { aggregate { count plain: count(columns: owner_id) dist: count(columns: owner_id, distinct: true) } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 0, + "plain": 0, + "dist": 0 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-minmax-mixed-types.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-minmax-mixed-types.json new file mode 100644 index 0000000000..e6b00970bd --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-minmax-mixed-types.json @@ -0,0 +1,30 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate(where: {id: {_eq: \"missing\"}}) { aggregate { count min { id enumField timestamp int_ float_ } max { id enumField timestamp int_ float_ } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "count": 0, + "min": { + "id": null, + "enumField": null, + "timestamp": null, + "int_": null, + "float_": null + }, + "max": { + "id": null, + "enumField": null, + "timestamp": null, + "int_": null, + "float_": null + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-numeric-all-operators.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-numeric-all-operators.json new file mode 100644 index 0000000000..d926af70ed --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-numeric-all-operators.json @@ -0,0 +1,46 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate(where: {id: {_eq: \"missing\"}}) { aggregate { count sum { tokenId } avg { tokenId } min { tokenId } max { tokenId } stddev { tokenId } stddev_pop { tokenId } stddev_samp { tokenId } var_pop { tokenId } var_samp { tokenId } variance { tokenId } } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 0, + "sum": { + "tokenId": null + }, + "avg": { + "tokenId": null + }, + "min": { + "tokenId": null + }, + "max": { + "tokenId": null + }, + "stddev": { + "tokenId": null + }, + "stddev_pop": { + "tokenId": null + }, + "stddev_samp": { + "tokenId": null + }, + "var_pop": { + "tokenId": null + }, + "var_samp": { + "tokenId": null + }, + "variance": { + "tokenId": null + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-with-nodes.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-with-nodes.json new file mode 100644 index 0000000000..1682387379 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-empty-with-nodes.json @@ -0,0 +1,17 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate(where: {id: {_eq: \"missing\"}}) { aggregate { count } nodes { id tokenId owner { id } } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 0 + }, + "nodes": [] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-avg-timestamp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-avg-timestamp.json new file mode 100644 index 0000000000..aa19a95c75 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-avg-timestamp.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { avg { timestamp } } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'timestamp' not found in type: 'EntityWithAllNonArrayTypes_avg_fields'", + "extensions": { + "path": "$.selectionSet.EntityWithAllNonArrayTypes_aggregate.selectionSet.aggregate.selectionSet.avg.selectionSet.timestamp", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-count-distinct-wrong-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-count-distinct-wrong-type.json new file mode 100644 index 0000000000..bf48214f59 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-count-distinct-wrong-type.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { count(distinct: \"yes\") } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected a boolean for type 'Boolean', but found a string", + "extensions": { + "path": "$.selectionSet.User_aggregate.selectionSet.aggregate.selectionSet.count.args.distinct", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-count-unknown-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-count-unknown-column.json new file mode 100644 index 0000000000..c9d63d69ee --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-count-unknown-column.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { count(columns: [notAColumn]) } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected one of the values ['id', 'accountType', 'address', 'gravatar_id', 'updatesCountOnUserForTesting'] for type 'User_select_column', but found 'notAColumn'", + "extensions": { + "path": "$.selectionSet.User_aggregate.selectionSet.aggregate.selectionSet.count.args.columns[0]", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-min-bool.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-min-bool.json new file mode 100644 index 0000000000..bd27cbb0cc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-min-bool.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { bool } } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'bool' not found in type: 'EntityWithAllNonArrayTypes_min_fields'", + "extensions": { + "path": "$.selectionSet.EntityWithAllNonArrayTypes_aggregate.selectionSet.aggregate.selectionSet.min.selectionSet.bool", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-sum-jsonb.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-sum-jsonb.json new file mode 100644 index 0000000000..8c42c66cad --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-sum-jsonb.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ raw_events_aggregate { aggregate { sum { params } } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'params' not found in type: 'raw_events_sum_fields'", + "extensions": { + "path": "$.selectionSet.raw_events_aggregate.selectionSet.aggregate.selectionSet.sum.selectionSet.params", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-sum-text-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-sum-text-column.json new file mode 100644 index 0000000000..11d87bf1fc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-sum-text-column.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { sum { id } } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'id' not found in type: 'Token_sum_fields'", + "extensions": { + "path": "$.selectionSet.Token_aggregate.selectionSet.aggregate.selectionSet.sum.selectionSet.id", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-variance-enum.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-variance-enum.json new file mode 100644 index 0000000000..ce7a9a7c00 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-error-variance-enum.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { variance { enumField } } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'enumField' not found in type: 'EntityWithAllNonArrayTypes_variance_fields'", + "extensions": { + "path": "$.selectionSet.EntityWithAllNonArrayTypes_aggregate.selectionSet.aggregate.selectionSet.variance.selectionSet.enumField", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-float8-avg-nan.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-float8-avg-nan.json new file mode 100644 index 0000000000..7aa65320fe --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-float8-avg-nan.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { avg { optFloat } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "avg": { + "optFloat": "NaN" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-float8-minmax-infinity.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-float8-minmax-infinity.json new file mode 100644 index 0000000000..ccd0d7669e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-float8-minmax-infinity.json @@ -0,0 +1,22 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { float_ } max { float_ optFloat } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "min": { + "float_": "-Infinity" + }, + "max": { + "float_": "Infinity", + "optFloat": "NaN" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-float8-sum-infinity-nan.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-float8-sum-infinity-nan.json new file mode 100644 index 0000000000..6516d6474d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-float8-sum-infinity-nan.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { sum { float_ } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "sum": { + "float_": "NaN" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-meta-float4-matrix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-meta-float4-matrix.json new file mode 100644 index 0000000000..ccd12eb106 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-meta-float4-matrix.json @@ -0,0 +1,34 @@ +{ + "role": "admin", + "request": { + "query": "{ _meta_aggregate { aggregate { count sum { eventsProcessed } avg { eventsProcessed } min { eventsProcessed } max { eventsProcessed } stddev { eventsProcessed } var_pop { eventsProcessed } } } }" + }, + "status": 200, + "body": { + "data": { + "_meta_aggregate": { + "aggregate": { + "count": 2, + "sum": { + "eventsProcessed": 2147487700 + }, + "avg": { + "eventsProcessed": 1073743872 + }, + "min": { + "eventsProcessed": 0 + }, + "max": { + "eventsProcessed": 2147487700 + }, + "stddev": { + "eventsProcessed": 1518503146.2974005 + }, + "var_pop": { + "eventsProcessed": 1152925902657552400 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-meta-int-sum-nullable.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-meta-int-sum-nullable.json new file mode 100644 index 0000000000..bb6418f92c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-meta-int-sum-nullable.json @@ -0,0 +1,21 @@ +{ + "role": "admin", + "request": { + "query": "{ _meta_aggregate { aggregate { sum { endBlock firstEventBlock startBlock progressBlock } } } }" + }, + "status": 200, + "body": { + "data": { + "_meta_aggregate": { + "aggregate": { + "sum": { + "endBlock": 5000, + "firstEventBlock": 10861674, + "startBlock": 1, + "progressBlock": 10865773 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-meta-minmax-timestamptz.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-meta-minmax-timestamptz.json new file mode 100644 index 0000000000..768f8e3209 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-meta-minmax-timestamptz.json @@ -0,0 +1,31 @@ +{ + "role": "admin", + "request": { + "query": "{ _meta_aggregate { aggregate { min { readyAt } max { readyAt } } } chain_metadata_aggregate { aggregate { min { timestamp_caught_up_to_head_or_endblock } max { timestamp_caught_up_to_head_or_endblock } } } }" + }, + "status": 200, + "body": { + "data": { + "_meta_aggregate": { + "aggregate": { + "min": { + "readyAt": "2024-11-01T10:20:30.456+00:00" + }, + "max": { + "readyAt": "2024-11-01T10:20:30.456+00:00" + } + } + }, + "chain_metadata_aggregate": { + "aggregate": { + "min": { + "timestamp_caught_up_to_head_or_endblock": "2024-11-01T10:20:30.456+00:00" + }, + "max": { + "timestamp_caught_up_to_head_or_endblock": "2024-11-01T10:20:30.456+00:00" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-enum.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-enum.json new file mode 100644 index 0000000000..402685785f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-enum.json @@ -0,0 +1,23 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { enumField optEnumField } max { enumField optEnumField } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "min": { + "enumField": "ADMIN", + "optEnumField": "ADMIN" + }, + "max": { + "enumField": "USER", + "optEnumField": "USER" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-text-columns.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-text-columns.json new file mode 100644 index 0000000000..b2211d7db0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-text-columns.json @@ -0,0 +1,25 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { min { id collection_id owner_id } max { id collection_id owner_id } } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "min": { + "id": "tok-1", + "collection_id": "coll-1", + "owner_id": "user \"quoted\" 🚀" + }, + "max": { + "id": "tok-9", + "collection_id": "coll-missing", + "owner_id": "user-missing" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-text-unicode-empty.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-text-unicode-empty.json new file mode 100644 index 0000000000..c04a9b013c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-text-unicode-empty.json @@ -0,0 +1,23 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { string optString } max { string optString } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "min": { + "string": "", + "optString": "" + }, + "max": { + "string": "with \"double\" and 'single' and back\\slash and\nnewline and\ttab", + "optString": "x" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-timestamptz.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-timestamptz.json new file mode 100644 index 0000000000..92c22a7a4b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-timestamptz.json @@ -0,0 +1,23 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { timestamp optTimestamp } max { timestamp optTimestamp } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "min": { + "timestamp": "1970-01-01T00:00:00+00:00", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + }, + "max": { + "timestamp": "9999-12-31T23:59:59.999999+00:00", + "optTimestamp": "2024-12-26T02:30:00+00:00" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-user-mixed.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-user-mixed.json new file mode 100644 index 0000000000..cafac4a2db --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-minmax-user-mixed.json @@ -0,0 +1,25 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { min { accountType address gravatar_id } max { accountType address gravatar_id } } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "min": { + "accountType": "ADMIN", + "address": "0xaaaa000000000000000000000000000000000001", + "gravatar_id": "grav-1" + }, + "max": { + "accountType": "USER", + "address": "0xaaaa000000000000000000000000000000000006", + "gravatar_id": "grav-missing" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-agg-empty-owner.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-agg-empty-owner.json new file mode 100644 index 0000000000..02253d69ca --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-agg-empty-owner.json @@ -0,0 +1,32 @@ +{ + "role": "admin", + "request": { + "query": "{ User_by_pk(id: \"user-dangling\") { id tokens_aggregate { aggregate { count sum { tokenId } avg { tokenId } min { tokenId } max { tokenId } } nodes { id } } } }" + }, + "status": 200, + "body": { + "data": { + "User_by_pk": { + "id": "user-dangling", + "tokens_aggregate": { + "aggregate": { + "count": 0, + "sum": { + "tokenId": null + }, + "avg": { + "tokenId": null + }, + "min": { + "tokenId": null + }, + "max": { + "tokenId": null + } + }, + "nodes": [] + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-agg-where-order-nodes.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-agg-where-order-nodes.json new file mode 100644 index 0000000000..79beab3ab9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-agg-where-order-nodes.json @@ -0,0 +1,75 @@ +{ + "role": "admin", + "request": { + "query": "{ NftCollection(order_by: {id: asc}) { id tokens_aggregate(where: {owner_id: {_like: \"user-%\"}}, order_by: {tokenId: asc}, limit: 3) { aggregate { count max { tokenId } } nodes { id tokenId } } } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-1", + "tokens_aggregate": { + "aggregate": { + "count": 3, + "max": { + "tokenId": "2" + } + }, + "nodes": [ + { + "id": "tok-1", + "tokenId": "0" + }, + { + "id": "tok-2", + "tokenId": "1" + }, + { + "id": "tok-3", + "tokenId": "2" + } + ] + } + }, + { + "id": "coll-2", + "tokens_aggregate": { + "aggregate": { + "count": 3, + "max": { + "tokenId": "1000000000000000000000000000000" + } + }, + "nodes": [ + { + "id": "tok-5", + "tokenId": "-5" + }, + { + "id": "tok-6", + "tokenId": "123456789" + }, + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + } + ] + } + }, + { + "id": "coll-3", + "tokens_aggregate": { + "aggregate": { + "count": 0, + "max": { + "tokenId": null + } + }, + "nodes": [] + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-count-distinct.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-count-distinct.json new file mode 100644 index 0000000000..9045d5db7a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-count-distinct.json @@ -0,0 +1,37 @@ +{ + "role": "admin", + "request": { + "query": "{ NftCollection(order_by: {id: asc}) { id tokens_aggregate { aggregate { count(columns: owner_id, distinct: true) } } } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-1", + "tokens_aggregate": { + "aggregate": { + "count": 3 + } + } + }, + { + "id": "coll-2", + "tokens_aggregate": { + "aggregate": { + "count": 5 + } + } + }, + { + "id": "coll-3", + "tokens_aggregate": { + "aggregate": { + "count": 0 + } + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-full-combo.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-full-combo.json new file mode 100644 index 0000000000..6efad4d51b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-nested-full-combo.json @@ -0,0 +1,121 @@ +{ + "role": "admin", + "request": { + "query": "{ User(order_by: {id: asc}) { id tokens_aggregate(where: {tokenId: {_gte: 0}}, distinct_on: collection_id, order_by: [{collection_id: asc}, {tokenId: desc}], limit: 2, offset: 1) { aggregate { count sum { tokenId } min { tokenId } } nodes { id collection_id tokenId } } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "tokens_aggregate": { + "aggregate": { + "count": 0, + "sum": { + "tokenId": null + }, + "min": { + "tokenId": null + } + }, + "nodes": [] + } + }, + { + "id": "user-1", + "tokens_aggregate": { + "aggregate": { + "count": 1, + "sum": { + "tokenId": "7" + }, + "min": { + "tokenId": "7" + } + }, + "nodes": [ + { + "id": "tok-7", + "collection_id": "coll-missing", + "tokenId": "7" + } + ] + } + }, + { + "id": "user-2", + "tokens_aggregate": { + "aggregate": { + "count": 1, + "sum": { + "tokenId": "1000000000000000000000000000000" + }, + "min": { + "tokenId": "1000000000000000000000000000000" + } + }, + "nodes": [ + { + "id": "tok-4", + "collection_id": "coll-2", + "tokenId": "1000000000000000000000000000000" + } + ] + } + }, + { + "id": "user-3", + "tokens_aggregate": { + "aggregate": { + "count": 0, + "sum": { + "tokenId": null + }, + "min": { + "tokenId": null + } + }, + "nodes": [] + } + }, + { + "id": "user-4", + "tokens_aggregate": { + "aggregate": { + "count": 1, + "sum": { + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + "min": { + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + }, + "nodes": [ + { + "id": "tok-9", + "collection_id": "coll-2", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ] + } + }, + { + "id": "user-dangling", + "tokens_aggregate": { + "aggregate": { + "count": 0, + "sum": { + "tokenId": null + }, + "min": { + "tokenId": null + } + }, + "nodes": [] + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-avg-vs-int-avg.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-avg-vs-int-avg.json new file mode 100644 index 0000000000..33683c9696 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-avg-vs-int-avg.json @@ -0,0 +1,19 @@ +{ + "role": "admin", + "request": { + "query": "{ raw_events_aggregate { aggregate { avg { event_id log_index } } } }" + }, + "status": 200, + "body": { + "data": { + "raw_events_aggregate": { + "aggregate": { + "avg": { + "event_id": "2767011611056432744", + "log_index": 0.8 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-minmax.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-minmax.json new file mode 100644 index 0000000000..7f0c14b1fa --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-minmax.json @@ -0,0 +1,23 @@ +{ + "role": "admin", + "request": { + "query": "{ raw_events_aggregate { aggregate { min { event_id serial } max { event_id serial } } } }" + }, + "status": 200, + "body": { + "data": { + "raw_events_aggregate": { + "aggregate": { + "min": { + "event_id": "1", + "serial": "1" + }, + "max": { + "event_id": "4611686018427387906", + "serial": "5" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-stddev-variance.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-stddev-variance.json new file mode 100644 index 0000000000..35b418fb17 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-stddev-variance.json @@ -0,0 +1,27 @@ +{ + "role": "admin", + "request": { + "query": "{ raw_events_aggregate { aggregate { stddev { event_id } stddev_pop { event_id } var_pop { event_id } variance { event_id } } } }" + }, + "status": 200, + "body": { + "data": { + "raw_events_aggregate": { + "aggregate": { + "stddev": { + "event_id": "2525924460423865524" + }, + "stddev_pop": { + "event_id": "2259255519814896225" + }, + "var_pop": { + "event_id": "5104235503814076950843814467053950075" + }, + "variance": { + "event_id": "6380294379767596188554768083817437594" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-sum.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-sum.json new file mode 100644 index 0000000000..179fcfdd17 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-bigint-sum.json @@ -0,0 +1,19 @@ +{ + "role": "admin", + "request": { + "query": "{ raw_events_aggregate { aggregate { sum { event_id serial } } } }" + }, + "status": 200, + "body": { + "data": { + "raw_events_aggregate": { + "aggregate": { + "sum": { + "event_id": "13835058055282163718", + "serial": "15" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-count-distinct-text-and-pair.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-count-distinct-text-and-pair.json new file mode 100644 index 0000000000..58ee3c8537 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-count-distinct-text-and-pair.json @@ -0,0 +1,17 @@ +{ + "role": "admin", + "request": { + "query": "{ raw_events_aggregate { aggregate { hashes: count(columns: block_hash, distinct: true) pairs: count(columns: [chain_id, block_number], distinct: true) } } }" + }, + "status": 200, + "body": { + "data": { + "raw_events_aggregate": { + "aggregate": { + "hashes": 4, + "pairs": 4 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-int-sum-overflows-int32.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-int-sum-overflows-int32.json new file mode 100644 index 0000000000..5119ae2f8e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-raw-int-sum-overflows-int32.json @@ -0,0 +1,21 @@ +{ + "role": "admin", + "request": { + "query": "{ raw_events_aggregate { aggregate { sum { chain_id block_number block_timestamp log_index } } } }" + }, + "status": 200, + "body": { + "data": { + "raw_events_aggregate": { + "aggregate": { + "sum": { + "chain_id": 2677, + "block_number": 32585026, + "block_timestamp": 7800000072, + "log_index": 4 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-root-distinct-on-aggregate.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-root-distinct-on-aggregate.json new file mode 100644 index 0000000000..e38cc0ba6b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-root-distinct-on-aggregate.json @@ -0,0 +1,33 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate(distinct_on: collection_id, order_by: [{collection_id: asc}, {id: asc}]) { aggregate { count sum { tokenId } } nodes { id collection_id } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 3, + "sum": { + "tokenId": "1000000000000000000000000000007" + } + }, + "nodes": [ + { + "id": "tok-1", + "collection_id": "coll-1" + }, + { + "id": "tok-4", + "collection_id": "coll-2" + }, + { + "id": "tok-7", + "collection_id": "coll-missing" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-bigdecimal-full-matrix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-bigdecimal-full-matrix.json new file mode 100644 index 0000000000..c5524924a7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-bigdecimal-full-matrix.json @@ -0,0 +1,38 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { count sum { bigDecimal bigDecimalWithConfig } avg { bigDecimal bigDecimalWithConfig } min { bigDecimal bigDecimalWithConfig } max { bigDecimal bigDecimalWithConfig } stddev { bigDecimal } var_samp { bigDecimalWithConfig } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "count": 8, + "sum": { + "bigDecimal": "12345678901234567994.613456789", + "bigDecimalWithConfig": "107.00000000" + }, + "avg": { + "bigDecimal": "1543209862654320999.326682099", + "bigDecimalWithConfig": "13.3750000000000000" + }, + "min": { + "bigDecimal": "-1.5", + "bigDecimalWithConfig": "-0.00000001" + }, + "max": { + "bigDecimal": "12345678901234567890.123456789", + "bigDecimalWithConfig": "99.99999999" + }, + "stddev": { + "bigDecimal": "4364856634707324026.114560125832717618" + }, + "var_samp": { + "bigDecimalWithConfig": "1226.4821425742857143" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-bigint-full-matrix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-bigint-full-matrix.json new file mode 100644 index 0000000000..468a03bb18 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-bigint-full-matrix.json @@ -0,0 +1,46 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { count sum { bigInt } avg { bigInt } min { bigInt } max { bigInt } stddev { bigInt } stddev_pop { bigInt } stddev_samp { bigInt } var_pop { bigInt } var_samp { bigInt } variance { bigInt } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "count": 8, + "sum": { + "bigInt": "10000000000000000000000000000000000000000000000000000000000000000000000000158" + }, + "avg": { + "bigInt": "1250000000000000000000000000000000000000000000000000000000000000000000000020" + }, + "min": { + "bigInt": "-1" + }, + "max": { + "bigInt": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + "stddev": { + "bigInt": "3535533905932737622004221810524245196424179688442370182941699344976831196147" + }, + "stddev_pop": { + "bigInt": "3307189138830738238127019692049075532137823978853062725460418074001336029030" + }, + "stddev_samp": { + "bigInt": "3535533905932737622004221810524245196424179688442370182941699344976831196147" + }, + "var_pop": { + "bigInt": "10937499999999999999999999999999999999999999999999999999999999999999999999948125000000000000000000000000000000000000000000000000000000000000000000001099" + }, + "var_samp": { + "bigInt": "12499999999999999999999999999999999999999999999999999999999999999999999999940714285714285714285714285714285714285714285714285714285714285714285714286971" + }, + "variance": { + "bigInt": "12499999999999999999999999999999999999999999999999999999999999999999999999940714285714285714285714285714285714285714285714285714285714285714285714286971" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-float8-full-matrix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-float8-full-matrix.json new file mode 100644 index 0000000000..282112ba05 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-float8-full-matrix.json @@ -0,0 +1,46 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate(where: {id: {_in: [\"scalar-1\", \"scalar-nulls\", \"scalar-unicode\", \"scalar-quotes\", \"scalar-empty\"]}}) { aggregate { count sum { float_ } avg { float_ } min { float_ } max { float_ } stddev { float_ } stddev_pop { float_ } stddev_samp { float_ } var_pop { float_ } var_samp { float_ } variance { float_ } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "count": 5, + "sum": { + "float_": "-2.04159" + }, + "avg": { + "float_": "-0.40831799999999996" + }, + "min": { + "float_": "-3.14159" + }, + "max": { + "float_": "1.5" + }, + "stddev": { + "float_": "1.698968053148734" + }, + "stddev_pop": { + "float_": "1.5196032233764178" + }, + "stddev_samp": { + "float_": "1.698968053148734" + }, + "var_pop": { + "float_": "2.3091939564959993" + }, + "var_samp": { + "float_": "2.886492445619999" + }, + "variance": { + "float_": "2.886492445619999" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-int-full-matrix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-int-full-matrix.json new file mode 100644 index 0000000000..298d5e3958 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-int-full-matrix.json @@ -0,0 +1,46 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { count sum { int_ } avg { int_ } min { int_ } max { int_ } stddev { int_ } stddev_pop { int_ } stddev_samp { int_ } var_pop { int_ } var_samp { int_ } variance { int_ } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "count": 8, + "sum": { + "int_": 2147483659 + }, + "avg": { + "int_": 268435457.375 + }, + "min": { + "int_": -2 + }, + "max": { + "int_": 2147483647 + }, + "stddev": { + "int_": 759250124 + }, + "stddev_pop": { + "int_": 710213459 + }, + "stddev_samp": { + "int_": 759250124 + }, + "var_pop": { + "int_": 504403156990427140 + }, + "var_samp": { + "int_": 576460750846202430 + }, + "variance": { + "int_": 576460750846202430 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-optint-null-handling.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-optint-null-handling.json new file mode 100644 index 0000000000..2804c01214 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-scalars-optint-null-handling.json @@ -0,0 +1,28 @@ +{ + "role": "admin", + "request": { + "query": "{ EntityWithAllNonArrayTypes_aggregate { aggregate { count(columns: optInt) sum { optInt } avg { optInt } min { optInt } max { optInt } } } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_aggregate": { + "aggregate": { + "count": 5, + "sum": { + "optInt": -2147483628 + }, + "avg": { + "optInt": -429496725.6 + }, + "min": { + "optInt": -2147483648 + }, + "max": { + "optInt": 10 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-sim-int-full-matrix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-sim-int-full-matrix.json new file mode 100644 index 0000000000..024a02b5d1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-sim-int-full-matrix.json @@ -0,0 +1,54 @@ +{ + "role": "admin", + "request": { + "query": "{ SimulateTestEvent_aggregate { aggregate { count sum { blockNumber logIndex timestamp } avg { blockNumber logIndex timestamp } min { blockNumber logIndex timestamp } max { blockNumber logIndex timestamp } stddev { logIndex } stddev_pop { logIndex } stddev_samp { logIndex } var_pop { timestamp } var_samp { timestamp } variance { timestamp } } } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent_aggregate": { + "aggregate": { + "count": 5, + "sum": { + "blockNumber": 506, + "logIndex": 8, + "timestamp": 8500000072 + }, + "avg": { + "blockNumber": 101.2, + "logIndex": 1.6, + "timestamp": 1700000014.4 + }, + "min": { + "blockNumber": 100, + "logIndex": 0, + "timestamp": 1700000000 + }, + "max": { + "blockNumber": 103, + "logIndex": 5, + "timestamp": 1700000036 + }, + "stddev": { + "logIndex": 2.073644135332772 + }, + "stddev_pop": { + "logIndex": 1.8547236990991407 + }, + "stddev_samp": { + "logIndex": 2.073644135332772 + }, + "var_pop": { + "timestamp": 195.84 + }, + "var_samp": { + "timestamp": 244.8 + }, + "variance": { + "timestamp": 244.8 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-single-row-stddev-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-single-row-stddev-null.json new file mode 100644 index 0000000000..7cab2873ef --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-single-row-stddev-null.json @@ -0,0 +1,34 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate(where: {id: {_eq: \"tok-1\"}}) { aggregate { count stddev { tokenId } stddev_pop { tokenId } stddev_samp { tokenId } var_pop { tokenId } var_samp { tokenId } variance { tokenId } } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 1, + "stddev": { + "tokenId": null + }, + "stddev_pop": { + "tokenId": "0" + }, + "stddev_samp": { + "tokenId": null + }, + "var_pop": { + "tokenId": "0" + }, + "var_samp": { + "tokenId": null + }, + "variance": { + "tokenId": null + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-token-numeric-full-matrix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-token-numeric-full-matrix.json new file mode 100644 index 0000000000..00d0b017c5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-token-numeric-full-matrix.json @@ -0,0 +1,46 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { count sum { tokenId } avg { tokenId } min { tokenId } max { tokenId } stddev { tokenId } stddev_pop { tokenId } stddev_samp { tokenId } var_pop { tokenId } var_samp { tokenId } variance { tokenId } } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "aggregate": { + "count": 10, + "sum": { + "tokenId": "10000000000000000000000000000000000000000000001000000000000000000000123456811" + }, + "avg": { + "tokenId": "1000000000000000000000000000000000000000000000100000000000000000000012345681" + }, + "min": { + "tokenId": "-5" + }, + "max": { + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + "stddev": { + "tokenId": "3162277660168379331998893544432718533719555139290080408411189526881491283648" + }, + "stddev_pop": { + "tokenId": "2999999999999999999999999999999999999999999999966666666666666666666662551439" + }, + "stddev_samp": { + "tokenId": "3162277660168379331998893544432718533719555139290080408411189526881491283648" + }, + "var_pop": { + "tokenId": "8999999999999999999999999999999999999999999999799999999999999999999975308635800000000000000089999999999999999999997530863780000000000001371742033196179" + }, + "var_samp": { + "tokenId": "9999999999999999999999999999999999999999999999777777777777777777777750342928666666666666666766666666666666666666663923181977777777777779301935592440199" + }, + "variance": { + "tokenId": "9999999999999999999999999999999999999999999999777777777777777777777750342928666666666666666766666666666666666666663923181977777777777779301935592440199" + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-user-avg-precision.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-user-avg-precision.json new file mode 100644 index 0000000000..78c5d429c9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-user-avg-precision.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { avg { updatesCountOnUserForTesting } } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "avg": { + "updatesCountOnUserForTesting": 8.833333333333334 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/am-user-int-full-matrix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/am-user-int-full-matrix.json new file mode 100644 index 0000000000..2d53574aff --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/am-user-int-full-matrix.json @@ -0,0 +1,46 @@ +{ + "role": "admin", + "request": { + "query": "{ User_aggregate { aggregate { count sum { updatesCountOnUserForTesting } avg { updatesCountOnUserForTesting } min { updatesCountOnUserForTesting } max { updatesCountOnUserForTesting } stddev { updatesCountOnUserForTesting } stddev_pop { updatesCountOnUserForTesting } stddev_samp { updatesCountOnUserForTesting } var_pop { updatesCountOnUserForTesting } var_samp { updatesCountOnUserForTesting } variance { updatesCountOnUserForTesting } } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "count": 6, + "sum": { + "updatesCountOnUserForTesting": 53 + }, + "avg": { + "updatesCountOnUserForTesting": 8.833333333333334 + }, + "min": { + "updatesCountOnUserForTesting": -2147483648 + }, + "max": { + "updatesCountOnUserForTesting": 2147483647 + }, + "stddev": { + "updatesCountOnUserForTesting": 1358187913 + }, + "stddev_pop": { + "updatesCountOnUserForTesting": 1239850262 + }, + "stddev_samp": { + "updatesCountOnUserForTesting": 1358187913 + }, + "var_pop": { + "updatesCountOnUserForTesting": 1537228672093301800 + }, + "var_samp": { + "updatesCountOnUserForTesting": 1844674406511961900 + }, + "variance": { + "updatesCountOnUserForTesting": 1844674406511961900 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-63-char-table.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-63-char-table.json new file mode 100644 index 0000000000..025a8f0eed --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-63-char-table.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWith63LenghtName______________________________________one(order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWith63LenghtName______________________________________one": [ + { + "id": "long-1" + }, + { + "id": "long-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-admin-role.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-admin-role.json new file mode 100644 index 0000000000..7fdee6b778 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-admin-role.json @@ -0,0 +1,37 @@ +{ + "role": "admin", + "request": { + "query": "{ User(order_by: {id: asc}) { id address } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005" + }, + { + "id": "user-1", + "address": "0xaaaa000000000000000000000000000000000001" + }, + { + "id": "user-2", + "address": "0xaaaa000000000000000000000000000000000002" + }, + { + "id": "user-3", + "address": "0xaaaa000000000000000000000000000000000003" + }, + { + "id": "user-4", + "address": "0xaaaa000000000000000000000000000000000004" + }, + { + "id": "user-dangling", + "address": "0xaaaa000000000000000000000000000000000006" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-alias-two-roots-same-table.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-alias-two-roots-same-table.json new file mode 100644 index 0000000000..dec12f93db --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-alias-two-roots-same-table.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ first: User(order_by: {id: asc}, limit: 1) { id } last: User(order_by: {id: desc}, limit: 1) { id } }" + }, + "status": 200, + "body": { + "data": { + "first": [ + { + "id": "user \"quoted\" 🚀" + } + ], + "last": [ + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-aliases.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-aliases.json new file mode 100644 index 0000000000..cc40945ef2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-aliases.json @@ -0,0 +1,23 @@ +{ + "role": "public", + "request": { + "query": "{ renamed: User(order_by: {id: asc}, limit: 2) { theId: id addr: address t: __typename } }" + }, + "status": 200, + "body": { + "data": { + "renamed": [ + { + "theId": "user \"quoted\" 🚀", + "addr": "0xaaaa000000000000000000000000000000000005", + "t": "User" + }, + { + "theId": "user-1", + "addr": "0xaaaa000000000000000000000000000000000001", + "t": "User" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-by-pk-hit.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-by-pk-hit.json new file mode 100644 index 0000000000..cacf93a676 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-by-pk-hit.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"user-1\") { id address accountType } }" + }, + "status": 200, + "body": { + "data": { + "User_by_pk": { + "id": "user-1", + "address": "0xaaaa000000000000000000000000000000000001", + "accountType": "ADMIN" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-by-pk-miss.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-by-pk-miss.json new file mode 100644 index 0000000000..95ff17c53b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-by-pk-miss.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"nope\") { id } }" + }, + "status": 200, + "body": { + "data": { + "User_by_pk": null + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-by-pk-special-chars.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-by-pk-special-chars.json new file mode 100644 index 0000000000..91ee391fed --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-by-pk-special-chars.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"user \\\"quoted\\\" 🚀\") { id address } }" + }, + "status": 200, + "body": { + "data": { + "User_by_pk": { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-empty-table.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-empty-table.json new file mode 100644 index 0000000000..dcd5840ea9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-empty-table.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ CustomSelectionTestPass(where: {id: {_eq: \"missing\"}}) { id } }" + }, + "status": 200, + "body": { + "data": { + "CustomSelectionTestPass": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-fragment-spread.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-fragment-spread.json new file mode 100644 index 0000000000..a6db726198 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-fragment-spread.json @@ -0,0 +1,23 @@ +{ + "role": "public", + "request": { + "query": "fragment UserFields on User { id address accountType } { User(order_by: {id: asc}, limit: 2) { ...UserFields } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005", + "accountType": "USER" + }, + { + "id": "user-1", + "address": "0xaaaa000000000000000000000000000000000001", + "accountType": "ADMIN" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-inline-fragment.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-inline-fragment.json new file mode 100644 index 0000000000..60c975bef2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-inline-fragment.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 2) { ... on User { id accountType } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "accountType": "USER" + }, + { + "id": "user-1", + "accountType": "ADMIN" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-multiple-root-fields.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-multiple-root-fields.json new file mode 100644 index 0000000000..21455436b7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-multiple-root-fields.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}) { id } Gravatar(order_by: {id: asc}) { id } Token(order_by: {id: asc}, limit: 3) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ], + "Gravatar": [ + { + "id": "grav-1" + }, + { + "id": "grav-2" + }, + { + "id": "grav-3" + } + ], + "Token": [ + { + "id": "tok-1" + }, + { + "id": "tok-10" + }, + { + "id": "tok-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-named-operation.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-named-operation.json new file mode 100644 index 0000000000..7743881ef0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-named-operation.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "query Q { SimpleEntity(order_by: {id: asc}, limit: 1) { id value } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1", + "value": "v1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-nested-fragments.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-nested-fragments.json new file mode 100644 index 0000000000..460a15e09d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-nested-fragments.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "fragment A1 on User { id ...B1 } fragment B1 on User { address } { User(order_by: {id: asc}, limit: 1) { ...A1 } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-operation-name-selection.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-operation-name-selection.json new file mode 100644 index 0000000000..dd8cf10c49 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-operation-name-selection.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "query GetUsers { User(order_by: {id: asc}, limit: 1) { id } } query GetGravatars { Gravatar(order_by: {id: asc}, limit: 1) { id } }", + "operationName": "GetGravatars" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-restricted-field-name.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-restricted-field-name.json new file mode 100644 index 0000000000..e6d2065678 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-restricted-field-name.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithRestrictedReScriptField(order_by: {id: asc}) { id type } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithRestrictedReScriptField": [ + { + "id": "restricted-1", + "type": "the type field" + }, + { + "id": "restricted-2", + "type": "" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-same-field-twice.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-same-field-twice.json new file mode 100644 index 0000000000..25c50e89f2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-same-field-twice.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 1) { id id address address } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-select-all-users.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-select-all-users.json new file mode 100644 index 0000000000..763400979a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-select-all-users.json @@ -0,0 +1,55 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}) { id address gravatar_id updatesCountOnUserForTesting accountType } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005", + "gravatar_id": null, + "updatesCountOnUserForTesting": 5, + "accountType": "USER" + }, + { + "id": "user-1", + "address": "0xaaaa000000000000000000000000000000000001", + "gravatar_id": "grav-1", + "updatesCountOnUserForTesting": 0, + "accountType": "ADMIN" + }, + { + "id": "user-2", + "address": "0xaaaa000000000000000000000000000000000002", + "gravatar_id": "grav-2", + "updatesCountOnUserForTesting": 42, + "accountType": "USER" + }, + { + "id": "user-3", + "address": "0xaaaa000000000000000000000000000000000003", + "gravatar_id": null, + "updatesCountOnUserForTesting": 2147483647, + "accountType": "USER" + }, + { + "id": "user-4", + "address": "0xaaaa000000000000000000000000000000000004", + "gravatar_id": null, + "updatesCountOnUserForTesting": -2147483648, + "accountType": "ADMIN" + }, + { + "id": "user-dangling", + "address": "0xaaaa000000000000000000000000000000000006", + "gravatar_id": "grav-missing", + "updatesCountOnUserForTesting": 7, + "accountType": "USER" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-select-no-order.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-select-no-order.json new file mode 100644 index 0000000000..d1d9b7f84f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-select-no-order.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity { id value } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1", + "value": "v1" + }, + { + "id": "simple-2", + "value": "v2" + }, + { + "id": "simple-3", + "value": "v3" + }, + { + "id": "simple-4", + "value": "v4" + }, + { + "id": "simple-5", + "value": "v5" + }, + { + "id": "simple-6", + "value": "v6" + }, + { + "id": "simple-7", + "value": "v7" + }, + { + "id": "simple-8", + "value": "v8" + }, + { + "id": "simple-9", + "value": "v9" + }, + { + "id": "simple-10", + "value": "v10" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-skip-include-false.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-skip-include-false.json new file mode 100644 index 0000000000..54eca51cd4 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-skip-include-false.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "query ($withAddr: Boolean!, $skipType: Boolean!) { User(order_by: {id: asc}, limit: 2) { id address @include(if: $withAddr) accountType @skip(if: $skipType) } }", + "variables": { + "withAddr": false, + "skipType": false + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "accountType": "USER" + }, + { + "id": "user-1", + "accountType": "ADMIN" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-skip-include.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-skip-include.json new file mode 100644 index 0000000000..d32e34ee8c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-skip-include.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "query ($withAddr: Boolean!, $skipType: Boolean!) { User(order_by: {id: asc}, limit: 2) { id address @include(if: $withAddr) accountType @skip(if: $skipType) } }", + "variables": { + "withAddr": true, + "skipType": true + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005" + }, + { + "id": "user-1", + "address": "0xaaaa000000000000000000000000000000000001" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-typename-by-pk.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-typename-by-pk.json new file mode 100644 index 0000000000..dc73459fdc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-typename-by-pk.json @@ -0,0 +1,14 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"user-1\") { __typename } }" + }, + "status": 200, + "body": { + "data": { + "User_by_pk": { + "__typename": "User" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-typename-root.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-typename-root.json new file mode 100644 index 0000000000..c6db137aad --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-typename-root.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ __typename User(order_by: {id: asc}, limit: 1) { __typename id } }" + }, + "status": 200, + "body": { + "data": { + "__typename": "query_root", + "User": [ + { + "__typename": "User", + "id": "user \"quoted\" 🚀" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-variables-default-value.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-variables-default-value.json new file mode 100644 index 0000000000..8709493c65 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-variables-default-value.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "query ($lim: Int = 2) { User(order_by: {id: asc}, limit: $lim) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-variables-null-optional.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-variables-null-optional.json new file mode 100644 index 0000000000..0dd6c908f7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-variables-null-optional.json @@ -0,0 +1,34 @@ +{ + "role": "public", + "request": { + "query": "query ($lim: Int) { User(order_by: {id: asc}, limit: $lim) { id } }", + "variables": { + "lim": null + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/basic-variables-string.json b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-variables-string.json new file mode 100644 index 0000000000..c32f5250ee --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/basic-variables-string.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "query ($id: String!) { User_by_pk(id: $id) { id address } }", + "variables": { + "id": "user-2" + } + }, + "status": 200, + "body": { + "data": { + "User_by_pk": { + "id": "user-2", + "address": "0xaaaa000000000000000000000000000000000002" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-basic.json b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-basic.json new file mode 100644 index 0000000000..00f70f1584 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-basic.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ Token(distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}]) { id owner_id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-8", + "owner_id": "user \"quoted\" 🚀", + "tokenId": "8" + }, + { + "id": "tok-7", + "owner_id": "user-1", + "tokenId": "7" + }, + { + "id": "tok-4", + "owner_id": "user-2", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-5", + "owner_id": "user-3", + "tokenId": "-5" + }, + { + "id": "tok-9", + "owner_id": "user-4", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "tok-6", + "owner_id": "user-missing", + "tokenId": "123456789" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-enum-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-enum-column.json new file mode 100644 index 0000000000..7ca49c0637 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-enum-column.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(distinct_on: size, order_by: [{size: asc}, {id: asc}]) { id size } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-1", + "size": "SMALL" + }, + { + "id": "grav-2", + "size": "MEDIUM" + }, + { + "id": "grav-3", + "size": "LARGE" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-list.json new file mode 100644 index 0000000000..bd3939cef1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-list.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(distinct_on: [blockNumber], order_by: [{blockNumber: asc}, {logIndex: desc}]) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + }, + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + }, + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-multiple-columns.json b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-multiple-columns.json new file mode 100644 index 0000000000..bd660d55bd --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-multiple-columns.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(distinct_on: [blockNumber, timestamp], order_by: [{blockNumber: asc}, {timestamp: asc}, {logIndex: asc}]) { id blockNumber timestamp } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-1", + "blockNumber": 100, + "timestamp": 1700000000 + }, + { + "id": "sim-3", + "blockNumber": 101, + "timestamp": 1700000012 + }, + { + "id": "sim-4", + "blockNumber": 102, + "timestamp": 1700000024 + }, + { + "id": "sim-5", + "blockNumber": 103, + "timestamp": 1700000036 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-with-limit.json b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-with-limit.json new file mode 100644 index 0000000000..77c7749f6b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/distinct-on-with-limit.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ Token(distinct_on: collection_id, order_by: [{collection_id: asc}, {tokenId: desc}], limit: 2) { id collection_id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-10", + "collection_id": "coll-1" + }, + { + "id": "tok-9", + "collection_id": "coll-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-distinct-on-unknown-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-distinct-on-unknown-column.json new file mode 100644 index 0000000000..72382bcdb9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-distinct-on-unknown-column.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(distinct_on: notAColumn) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected one of the values ['id', 'accountType', 'address', 'gravatar_id', 'updatesCountOnUserForTesting'] for type 'User_select_column', but found 'notAColumn'", + "extensions": { + "path": "$.selectionSet.User.args.distinct_on[0]", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-limit-as-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-limit-as-list.json new file mode 100644 index 0000000000..5ced1a2b2b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-limit-as-list.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: [1]) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected a non-negative 32-bit integer for type 'Int', but found a list", + "extensions": { + "path": "$.selectionSet.User.args.limit", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-limit-as-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-limit-as-object.json new file mode 100644 index 0000000000..a5d7ed5d69 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-limit-as-object.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: {value: 5}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected a non-negative 32-bit integer for type 'Int', but found an object", + "extensions": { + "path": "$.selectionSet.User.args.limit", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-order-by-as-enum-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-order-by-as-enum-literal.json new file mode 100644 index 0000000000..289086f801 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-order-by-as-enum-literal.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: asc) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected an object for type 'User_order_by', but found an enum value", + "extensions": { + "path": "$.selectionSet.User.args.order_by[0]", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-order-by-as-string.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-order-by-as-string.json new file mode 100644 index 0000000000..c635807ac5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-order-by-as-string.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: \"asc\") { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected an object for type 'User_order_by', but found a string", + "extensions": { + "path": "$.selectionSet.User.args.order_by[0]", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-where-as-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-where-as-list.json new file mode 100644 index 0000000000..42bb88a6aa --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-where-as-list.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: [{id: {_eq: \"user-1\"}}]) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected an object for type 'User_bool_exp', but found a list", + "extensions": { + "path": "$.selectionSet.User.args.where", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-where-as-string.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-where-as-string.json new file mode 100644 index 0000000000..c09cfa641e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-arg-where-as-string.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: \"id\") { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected an object for type 'User_bool_exp', but found a string", + "extensions": { + "path": "$.selectionSet.User.args.where", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-body-lone-surrogate-in-query.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-body-lone-surrogate-in-query.json new file mode 100644 index 0000000000..01623f1249 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-body-lone-surrogate-in-query.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"\ud800\") { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "Cannot decode input: Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream", + "extensions": { + "path": "$", + "code": "invalid-json" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-by-pk-extra-unknown-arg.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-by-pk-extra-unknown-arg.json new file mode 100644 index 0000000000..2840e737a3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-by-pk-extra-unknown-arg.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"user-1\", bogus: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "'User_by_pk' has no argument named 'bogus'", + "extensions": { + "path": "$.selectionSet.User_by_pk", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-by-pk-id-null-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-by-pk-id-null-literal.json new file mode 100644 index 0000000000..ad612a73e5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-by-pk-id-null-literal.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: null) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "unexpected null value for type 'String'", + "extensions": { + "path": "$.selectionSet.User_by_pk.args.id", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-comments-only-query.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-comments-only-query.json new file mode 100644 index 0000000000..76e52343b4 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-comments-only-query.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "# just a comment\n# and another one" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-deep-nesting-40-levels.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-deep-nesting-40-levels.json new file mode 100644 index 0000000000..ae2cb53e4b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-deep-nesting-40-levels.json @@ -0,0 +1,134 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"user-1\") { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id gravatar { id owner { id } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } }" + }, + "status": 200, + "body": { + "data": { + "User_by_pk": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "id": "user-1" + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-directive-skip-on-query-operation.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-directive-skip-on-query-operation.json new file mode 100644 index 0000000000..f9de4d0d5e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-directive-skip-on-query-operation.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "query Q @skip(if: true) { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "directive 'skip' is not allowed on a query", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-duplicate-argument-name.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-duplicate-argument-name.json new file mode 100644 index 0000000000..e1274edfb4 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-duplicate-argument-name.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: 1, limit: 2) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-duplicate-key-in-input-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-duplicate-key-in-input-object.json new file mode 100644 index 0000000000..9cb337b864 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-duplicate-key-in-input-object.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {id: {_eq: \"user-1\", _eq: \"user-2\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-duplicate-variable-definition.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-duplicate-variable-definition.json new file mode 100644 index 0000000000..2a39011c4e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-duplicate-variable-definition.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($l: Int, $l: Int) { User(order_by: {id: asc}, limit: $l) { id } }", + "variables": { + "l": 1 + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "multiple definitions for variable \"l\"", + "extensions": { + "path": "$", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-empty-selection-braces-field.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-empty-selection-braces-field.json new file mode 100644 index 0000000000..d71d0c588e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-empty-selection-braces-field.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: 1) { } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-empty-selection-braces-root.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-empty-selection-braces-root.json new file mode 100644 index 0000000000..302e6d02a0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-empty-selection-braces-root.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-float-literal-overflow.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-float-literal-overflow.json new file mode 100644 index 0000000000..a51723c8e0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-float-literal-overflow.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {float_: {_lt: 1e400}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "The value 1.0e400 lies outside the bounds. Is it overflowing the float bounds?", + "extensions": { + "path": "$.selectionSet.EntityWithAllNonArrayTypes.args.where.float_._lt", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-fragment-on-enum-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-fragment-on-enum-type.json new file mode 100644 index 0000000000..1040c96ab2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-fragment-on-enum-type.json @@ -0,0 +1,14 @@ +{ + "role": "public", + "request": { + "query": "fragment F on order_by { x } { User(order_by: {id: asc}, limit: 1) { ...F } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + {} + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-fragment-on-scalar-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-fragment-on-scalar-type.json new file mode 100644 index 0000000000..92f696d33c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-fragment-on-scalar-type.json @@ -0,0 +1,14 @@ +{ + "role": "public", + "request": { + "query": "fragment F on String { length } { User(order_by: {id: asc}, limit: 1) { ...F } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + {} + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-inline-fragment-unknown-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-inline-fragment-unknown-type.json new file mode 100644 index 0000000000..10b2ae8a79 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-inline-fragment-unknown-type.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 1) { id ... on Bogus { id } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-inline-fragment-wrong-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-inline-fragment-wrong-type.json new file mode 100644 index 0000000000..c762b78b0d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-inline-fragment-wrong-type.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 1) { id ... on Gravatar { id } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-int-literal-overflow-int32.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-int-literal-overflow-int32.json new file mode 100644 index 0000000000..f05efb35fd --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-int-literal-overflow-int32.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 2147483648) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "The value 2.147483648e9 lies outside the bounds or is not an integer. Maybe it is a float, or is there integer overflow?", + "extensions": { + "path": "$.selectionSet.User.args.limit", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-int-literal-overflow-int64.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-int-literal-overflow-int64.json new file mode 100644 index 0000000000..4c44d6b270 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-int-literal-overflow-int64.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 9223372036854775808) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "The value 9.223372036854775808e18 lies outside the bounds or is not an integer. Maybe it is a float, or is there integer overflow?", + "extensions": { + "path": "$.selectionSet.User.args.limit", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-null-literal-limit.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-null-literal-limit.json new file mode 100644 index 0000000000..6a98345fa6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-null-literal-limit.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(limit: null, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-null-literal-where.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-null-literal-where.json new file mode 100644 index 0000000000..36acee1949 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-null-literal-where.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: null, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-opname-empty-string.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-opname-empty-string.json new file mode 100644 index 0000000000..2b177145dd --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-opname-empty-string.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "query Q { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }", + "operationName": "" + }, + "status": 200, + "body": { + "errors": [ + { + "message": " is not valid GraphQL name", + "extensions": { + "path": "$.operationName", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-string-bad-unicode-escape.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-string-bad-unicode-escape.json new file mode 100644 index 0000000000..3088d1fb83 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-string-bad-unicode-escape.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"\\uZZZZ\") { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-string-lone-surrogate-escape.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-string-lone-surrogate-escape.json new file mode 100644 index 0000000000..169cda9a0d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-string-lone-surrogate-escape.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"\\uD800\") { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-string-unknown-escape.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-string-unknown-escape.json new file mode 100644 index 0000000000..af0b2098c1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-string-unknown-escape.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"\\q\") { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-subscription-multiple-root-fields.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-subscription-multiple-root-fields.json new file mode 100644 index 0000000000..4240801638 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-subscription-multiple-root-fields.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "subscription { User(limit: 1) { id } Gravatar(limit: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "subscriptions must select one top level field", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-arg-aggregate-count.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-arg-aggregate-count.json new file mode 100644 index 0000000000..2b5c42ea2e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-arg-aggregate-count.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { count(bogus: true) } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "'count' has no argument named 'bogus'", + "extensions": { + "path": "$.selectionSet.Token_aggregate.selectionSet.aggregate.selectionSet.count", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-arg-on-scalar-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-arg-on-scalar-column.json new file mode 100644 index 0000000000..5b5e710a1e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-arg-on-scalar-column.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 1) { id address(bogus: 1) } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "'address' has no argument named 'bogus'", + "extensions": { + "path": "$.selectionSet.User.selectionSet.address", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-aggregate-body.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-aggregate-body.json new file mode 100644 index 0000000000..118518ed0d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-aggregate-body.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { aggregate { bogus } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'bogus' not found in type: 'Token_aggregate_fields'", + "extensions": { + "path": "$.selectionSet.Token_aggregate.selectionSet.aggregate.selectionSet.bogus", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-aggregate-wrapper.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-aggregate-wrapper.json new file mode 100644 index 0000000000..5bbbf5d0e2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-aggregate-wrapper.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate { bogus } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'bogus' not found in type: 'Token_aggregate'", + "extensions": { + "path": "$.selectionSet.Token_aggregate.selectionSet.bogus", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-array-rel.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-array-rel.json new file mode 100644 index 0000000000..a3f99c9f0c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-array-rel.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 1) { id tokens { id bogusField } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'bogusField' not found in type: 'Token'", + "extensions": { + "path": "$.selectionSet.User.selectionSet.tokens.selectionSet.bogusField", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-object-rel.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-object-rel.json new file mode 100644 index 0000000000..4f3f996c44 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-object-rel.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 1) { id gravatar { id bogusField } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'bogusField' not found in type: 'Gravatar'", + "extensions": { + "path": "$.selectionSet.User.selectionSet.gravatar.selectionSet.bogusField", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-root-typo.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-root-typo.json new file mode 100644 index 0000000000..bef50443d7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-field-root-typo.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ Userz { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'Userz' not found in type: 'query_root'", + "extensions": { + "path": "$.selectionSet.Userz", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-operation-type-keyword.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-operation-type-keyword.json new file mode 100644 index 0000000000..299ea33011 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-unknown-operation-type-keyword.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "queery { User { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-var-string-decl-used-as-int.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-var-string-decl-used-as-int.json new file mode 100644 index 0000000000..912955207d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-var-string-decl-used-as-int.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($l: String!) { User(order_by: {id: asc}, limit: $l) { id } }", + "variables": { + "l": "1" + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "variable 'l' is declared as 'String!', but used where 'Int' is expected", + "extensions": { + "path": "$.selectionSet.User.args.limit", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-var-wrong-name-used.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-var-wrong-name-used.json new file mode 100644 index 0000000000..07ea165c79 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-var-wrong-name-used.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($lim: Int) { User(order_by: {id: asc}, limit: $limit) { id } }", + "variables": { + "lim": 1 + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "unbound variable \"limit\"", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/em-whitespace-only-query.json b/packages/e2e-tests/fixtures/differential/snapshots/default/em-whitespace-only-query.json new file mode 100644 index 0000000000..d40d225989 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/em-whitespace-only-query.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": " \n\t " + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-admin-secret-wrong.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-admin-secret-wrong.json new file mode 100644 index 0000000000..c5d0c7fe9c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-admin-secret-wrong.json @@ -0,0 +1,18 @@ +{ + "role": "admin-wrong", + "request": { + "query": "{ User(limit: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "invalid \"x-hasura-admin-secret\"/\"x-hasura-access-key\"", + "extensions": { + "path": "$", + "code": "access-denied" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-aggregate-public-not-exposed.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-aggregate-public-not-exposed.json new file mode 100644 index 0000000000..06c1c79914 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-aggregate-public-not-exposed.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ Token_aggregate { aggregate { count } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'Token_aggregate' not found in type: 'query_root'", + "extensions": { + "path": "$.selectionSet.Token_aggregate", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-by-pk-missing-arg.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-by-pk-missing-arg.json new file mode 100644 index 0000000000..d23b395fda --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-by-pk-missing-arg.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "missing required field 'id'", + "extensions": { + "path": "$.selectionSet.User_by_pk.args.id", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-by-pk-wrong-arg-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-by-pk-wrong-arg-type.json new file mode 100644 index 0000000000..69055280e1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-by-pk-wrong-arg-type.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: 5) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "parsing Text failed, expected String, but encountered Number", + "extensions": { + "path": "$.selectionSet.User_by_pk.args.id", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-directive-unknown.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-directive-unknown.json new file mode 100644 index 0000000000..6167f67daa --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-directive-unknown.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: 1) { id @bogus } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "directive 'bogus' is not defined in the schema", + "extensions": { + "path": "$.selectionSet.User.selectionSet", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-distinct-on-without-matching-order.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-distinct-on-without-matching-order.json new file mode 100644 index 0000000000..d45c1ec9f7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-distinct-on-without-matching-order.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ Token(distinct_on: owner_id, order_by: {tokenId: asc}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "\"distinct_on\" columns must match initial \"order_by\" columns", + "extensions": { + "path": "$.selectionSet.Token.args", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-duplicate-operation-names.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-duplicate-operation-names.json new file mode 100644 index 0000000000..e3abcbc957 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-duplicate-operation-names.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "query A { User(limit: 1) { id } } query A { Gravatar(limit: 1) { id } }", + "operationName": "A" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-empty-query.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-empty-query.json new file mode 100644 index 0000000000..9a057e3701 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-empty-query.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-enum-as-string-order-by.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-enum-as-string-order-by.json new file mode 100644 index 0000000000..00641c2fec --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-enum-as-string-order-by.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: \"asc\"}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected an enum value for type 'order_by', but found a string", + "extensions": { + "path": "$.selectionSet.User.args.order_by[0].id", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-eq-null-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-eq-null-literal.json new file mode 100644 index 0000000000..671d0a3f75 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-eq-null-literal.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {gravatar_id: {_eq: null}}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "unexpected null value for type 'String'", + "extensions": { + "path": "$.selectionSet.User.args.where.gravatar_id._eq", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-float-for-int-filter.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-float-for-int-filter.json new file mode 100644 index 0000000000..94257a1b05 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-float-for-int-filter.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {updatesCountOnUserForTesting: {_eq: 1.5}}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "The value 1.5 lies outside the bounds or is not an integer. Maybe it is a float, or is there integer overflow?", + "extensions": { + "path": "$.selectionSet.User.args.where.updatesCountOnUserForTesting._eq", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-cycle.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-cycle.json new file mode 100644 index 0000000000..da5fbbf220 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-cycle.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "fragment A1 on User { ...B1 } fragment B1 on User { ...A1 } { User(limit: 1) { ...A1 } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "the fragment definition(s) A1 and B1 form a cycle", + "extensions": { + "path": "$.selectionSet.User.selectionSet.A1.selectionSet.B1.selectionSet", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-undefined.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-undefined.json new file mode 100644 index 0000000000..e728468afa --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-undefined.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: 1) { ...NoSuchFragment } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "reference to undefined fragment \"NoSuchFragment\"", + "extensions": { + "path": "$.selectionSet.User.selectionSet", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-unknown-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-unknown-type.json new file mode 100644 index 0000000000..eb51291912 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-unknown-type.json @@ -0,0 +1,14 @@ +{ + "role": "public", + "request": { + "query": "fragment F on Bogus { id } { User(limit: 1) { ...F } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + {} + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-unused.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-unused.json new file mode 100644 index 0000000000..111307ff61 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-fragment-unused.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "fragment Unused on User { id } { User(limit: 1) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-int-overflow-filter.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-int-overflow-filter.json new file mode 100644 index 0000000000..7ef3477cb3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-int-overflow-filter.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {updatesCountOnUserForTesting: {_eq: 99999999999999}}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "The value 9.9999999999999e13 lies outside the bounds or is not an integer. Maybe it is a float, or is there integer overflow?", + "extensions": { + "path": "$.selectionSet.User.args.where.updatesCountOnUserForTesting._eq", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-invalid-enum-value.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-invalid-enum-value.json new file mode 100644 index 0000000000..dfb73a40a2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-invalid-enum-value.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {accountType: {_eq: \"NOPE\"}}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "invalid input value for enum accounttype: \"NOPE\"", + "extensions": { + "path": "$", + "code": "data-exception" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-jsonb-path-invalid.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-jsonb-path-invalid.json new file mode 100644 index 0000000000..e9e82ba00d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-jsonb-path-invalid.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {id: {_eq: \"all-1\"}}) { json(path: \"totally broken [\") } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "parse json path error: totally broken [. Accept letters, digits, underscore (_) or hyphen (-) only. Use quotes enclosed in bracket ([\"...\"]) if there is any special character", + "extensions": { + "path": "$.selectionSet.EntityWithAllTypes.selectionSet.json.args", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-like-on-int-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-like-on-int-column.json new file mode 100644 index 0000000000..089370927e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-like-on-int-column.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {updatesCountOnUserForTesting: {_like: \"%1%\"}}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field '_like' not found in type: 'Int_comparison_exp'", + "extensions": { + "path": "$.selectionSet.User.args.where.updatesCountOnUserForTesting._like", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-limit-string.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-limit-string.json new file mode 100644 index 0000000000..36b955d0d5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-limit-string.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: \"5\") { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected a non-negative 32-bit integer for type 'Int', but found a string", + "extensions": { + "path": "$.selectionSet.User.args.limit", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-missing-required-variable.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-missing-required-variable.json new file mode 100644 index 0000000000..53721c13f0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-missing-required-variable.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "query ($id: String!) { User_by_pk(id: $id) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expecting a value for non-nullable variable: \"id\"", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-multiple-anonymous-operations.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-multiple-anonymous-operations.json new file mode 100644 index 0000000000..fdeacb0539 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-multiple-anonymous-operations.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: 1) { id } } { Gravatar(limit: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "exactly one operation has to be present in the document when operationName is not specified", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-multiple-ops-no-operation-name.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-multiple-ops-no-operation-name.json new file mode 100644 index 0000000000..38d0654b59 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-multiple-ops-no-operation-name.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "query A { User(limit: 1) { id } } query B { Gravatar(limit: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "exactly one operation has to be present in the document when operationName is not specified", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-mutation-public.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-mutation-public.json new file mode 100644 index 0000000000..fd8ab91b17 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-mutation-public.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "mutation { insert_User(objects: [{id: \"x\", address: \"0x\", updatesCountOnUserForTesting: 0, accountType: \"USER\"}]) { affected_rows } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "no mutations exist", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-negative-limit.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-negative-limit.json new file mode 100644 index 0000000000..37066c78e8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-negative-limit.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: -1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected a non-negative 32-bit integer for type 'Int', but found an integer", + "extensions": { + "path": "$.selectionSet.User.args.limit", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-negative-offset.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-negative-offset.json new file mode 100644 index 0000000000..12df557211 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-negative-offset.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}, offset: -5) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "OFFSET must not be negative", + "extensions": { + "path": "$", + "code": "data-exception" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-no-selection-set.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-no-selection-set.json new file mode 100644 index 0000000000..0e9ede33b6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-no-selection-set.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "missing selection set for 'User'", + "extensions": { + "path": "$.selectionSet.User.selectionSet", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-null-for-required-variable.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-null-for-required-variable.json new file mode 100644 index 0000000000..1a0447d395 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-null-for-required-variable.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($id: String!) { User_by_pk(id: $id) { id } }", + "variables": { + "id": null + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "null value found for non-nullable type: \"String!\"", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-operation-name-not-found.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-operation-name-not-found.json new file mode 100644 index 0000000000..dbdd235367 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-operation-name-not-found.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "query A { User(limit: 1) { id } }", + "operationName": "B" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "no such operation found in the document: \"B\"", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-scalar-with-selection.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-scalar-with-selection.json new file mode 100644 index 0000000000..328c54bde9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-scalar-with-selection.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: 1) { id { nested } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "unexpected subselection set for non-object field", + "extensions": { + "path": "$.selectionSet.User.selectionSet.id", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-skip-missing-if.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-skip-missing-if.json new file mode 100644 index 0000000000..a20599d8f1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-skip-missing-if.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: 1) { id @skip } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "missing required field 'if'", + "extensions": { + "path": "$.selectionSet.User.selectionSet.skip.args.if", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-subscription-over-http.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-subscription-over-http.json new file mode 100644 index 0000000000..a7ea61a9a8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-subscription-over-http.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "subscription { User(limit: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "subscriptions are not supported over HTTP, use websockets instead", + "extensions": { + "path": "$", + "code": "unexpected-payload" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-syntax.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-syntax.json new file mode 100644 index 0000000000..ce38c21137 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-syntax.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User { id " + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-undeclared-variable-used.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-undeclared-variable-used.json new file mode 100644 index 0000000000..541b68343d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-undeclared-variable-used.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ User(limit: $lim) { id } }", + "variables": { + "lim": 1 + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "unbound variable \"lim\"", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-argument.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-argument.json new file mode 100644 index 0000000000..a15855875f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-argument.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(bogus: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "'User' has no argument named 'bogus'", + "extensions": { + "path": "$.selectionSet.User", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-column.json new file mode 100644 index 0000000000..2203f6d994 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-column.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User { id notAColumn } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'notAColumn' not found in type: 'User'", + "extensions": { + "path": "$.selectionSet.User.selectionSet.notAColumn", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-op-in-bool-exp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-op-in-bool-exp.json new file mode 100644 index 0000000000..cdde52ada0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-op-in-bool-exp.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {id: {_bogus: \"x\"}}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field '_bogus' not found in type: 'String_comparison_exp'", + "extensions": { + "path": "$.selectionSet.User.args.where.id._bogus", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-root-field.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-root-field.json new file mode 100644 index 0000000000..b15147f3f8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-root-field.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ NotATable { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'NotATable' not found in type: 'query_root'", + "extensions": { + "path": "$.selectionSet.NotATable", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-variable-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-variable-type.json new file mode 100644 index 0000000000..f27eadac53 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unknown-variable-type.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "query ($w: Bogus_bool_exp) { User { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-unused-variable.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unused-variable.json new file mode 100644 index 0000000000..6592b4fa9a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-unused-variable.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($unused: Int) { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }", + "variables": { + "unused": 1 + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "unexpected variables in variableValues: unused", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-variable-wrong-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-variable-wrong-type.json new file mode 100644 index 0000000000..e68251b9a6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-variable-wrong-type.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($id: String!) { User_by_pk(id: $id) { id } }", + "variables": { + "id": 42 + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "parsing Text failed, expected String, but encountered Number", + "extensions": { + "path": "$.selectionSet.User_by_pk.args.id", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/error-where-wrong-type.json b/packages/e2e-tests/fixtures/differential/snapshots/default/error-where-wrong-type.json new file mode 100644 index 0000000000..545b1b4d3d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/error-where-wrong-type.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {updatesCountOnUserForTesting: {_eq: \"not-an-int\"}}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "invalid input syntax for type integer: \"not-an-int\"", + "extensions": { + "path": "$", + "code": "data-exception" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-chain-metadata-no-by-pk.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-chain-metadata-no-by-pk.json new file mode 100644 index 0000000000..96d0fc11d8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-chain-metadata-no-by-pk.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ chain_metadata(where: {chain_id: {_eq: 1337}}) { chain_id end_block timestamp_caught_up_to_head_or_endblock } }" + }, + "status": 200, + "body": { + "data": { + "chain_metadata": [ + { + "chain_id": 1337, + "end_block": 5000, + "timestamp_caught_up_to_head_or_endblock": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-chain-metadata-view.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-chain-metadata-view.json new file mode 100644 index 0000000000..b02bbf0071 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-chain-metadata-view.json @@ -0,0 +1,39 @@ +{ + "role": "public", + "request": { + "query": "{ chain_metadata(order_by: {chain_id: asc}) { block_height chain_id end_block first_event_block_number is_hyper_sync latest_fetched_block_number latest_processed_block num_batches_fetched num_events_processed start_block timestamp_caught_up_to_head_or_endblock } }" + }, + "status": 200, + "body": { + "data": { + "chain_metadata": [ + { + "block_height": 10861800, + "chain_id": 1, + "end_block": null, + "first_event_block_number": 10861674, + "is_hyper_sync": true, + "latest_fetched_block_number": 10861774, + "latest_processed_block": 10861774, + "num_batches_fetched": 0, + "num_events_processed": 2147487700, + "start_block": 0, + "timestamp_caught_up_to_head_or_endblock": "2024-11-01T10:20:30.456+00:00" + }, + { + "block_height": 4500, + "chain_id": 1337, + "end_block": 5000, + "first_event_block_number": null, + "is_hyper_sync": false, + "latest_fetched_block_number": 4000, + "latest_processed_block": 3999, + "num_batches_fetched": 0, + "num_events_processed": 0, + "start_block": 1, + "timestamp_caught_up_to_head_or_endblock": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-aggregate-admin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-aggregate-admin.json new file mode 100644 index 0000000000..0069576d40 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-aggregate-admin.json @@ -0,0 +1,19 @@ +{ + "role": "admin", + "request": { + "query": "{ _meta_aggregate { aggregate { count max { eventsProcessed } } } }" + }, + "status": 200, + "body": { + "data": { + "_meta_aggregate": { + "aggregate": { + "count": 2, + "max": { + "eventsProcessed": 2147487700 + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-float4-precision.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-float4-precision.json new file mode 100644 index 0000000000..2119861fe9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-float4-precision.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ _meta(where: {chainId: {_eq: 1}}) { chainId eventsProcessed } }" + }, + "status": 200, + "body": { + "data": { + "_meta": [ + { + "chainId": 1, + "eventsProcessed": 2147487700 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-view.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-view.json new file mode 100644 index 0000000000..39f4db865e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-view.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ _meta { chainId startBlock endBlock progressBlock bufferBlock firstEventBlock eventsProcessed sourceBlock readyAt isReady } }" + }, + "status": 200, + "body": { + "data": { + "_meta": [ + { + "chainId": 1, + "startBlock": 0, + "endBlock": null, + "progressBlock": 10861774, + "bufferBlock": 10861774, + "firstEventBlock": 10861674, + "eventsProcessed": 2147487700, + "sourceBlock": 10861800, + "readyAt": "2024-11-01T10:20:30.456+00:00", + "isReady": true + }, + { + "chainId": 1337, + "startBlock": 1, + "endBlock": 5000, + "progressBlock": 3999, + "bufferBlock": 4000, + "firstEventBlock": null, + "eventsProcessed": 0, + "sourceBlock": 4500, + "readyAt": null, + "isReady": false + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-where-ready.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-where-ready.json new file mode 100644 index 0000000000..604967f4f7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-meta-where-ready.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ _meta(where: {isReady: {_eq: true}}) { chainId readyAt } }" + }, + "status": 200, + "body": { + "data": { + "_meta": [ + { + "chainId": 1, + "readyAt": "2024-11-01T10:20:30.456+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-no-relationships-on-internal-tables.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-no-relationships-on-internal-tables.json new file mode 100644 index 0000000000..b632cc5c77 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-no-relationships-on-internal-tables.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(limit: 1, order_by: {serial: asc}) { serial } _meta(limit: 1) { chainId } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "1" + } + ], + "_meta": [ + { + "chainId": 1 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-bigint-filter.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-bigint-filter.json new file mode 100644 index 0000000000..2203b56397 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-bigint-filter.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(where: {event_id: {_gt: \"4611686018427387904\"}}, order_by: {serial: asc}) { serial event_id } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "2", + "event_id": "4611686018427387905" + }, + { + "serial": "3", + "event_id": "4611686018427387906" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-by-pk-miss.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-by-pk-miss.json new file mode 100644 index 0000000000..7e5b0554de --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-by-pk-miss.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events_by_pk(serial: 999999) { serial } }" + }, + "status": 200, + "body": { + "data": { + "raw_events_by_pk": null + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-by-pk.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-by-pk.json new file mode 100644 index 0000000000..2d62c217ef --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-by-pk.json @@ -0,0 +1,20 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events_by_pk(serial: 1) { serial event_name params } }" + }, + "status": 200, + "body": { + "data": { + "raw_events_by_pk": { + "serial": "1", + "event_name": "Transfer", + "params": { + "to": "0x1", + "from": "0x0", + "value": "100" + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-full.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-full.json new file mode 100644 index 0000000000..dec601890b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-full.json @@ -0,0 +1,125 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(order_by: {serial: asc}) { chain_id event_id event_name contract_name block_number log_index src_address block_hash block_timestamp block_fields transaction_fields params serial } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "chain_id": 1, + "event_id": "4611686018427387904", + "event_name": "Transfer", + "contract_name": "Gravatar", + "block_number": 10861674, + "log_index": 0, + "src_address": "0x2b2f78c5bf6d9c12ee1225d5f374aa91204580c3", + "block_hash": "0xblock1", + "block_timestamp": 1600000000, + "block_fields": { + "number": 10861674 + }, + "transaction_fields": { + "hash": "0xtx1", + "transactionIndex": 0 + }, + "params": { + "to": "0x1", + "from": "0x0", + "value": "100" + }, + "serial": "1" + }, + { + "chain_id": 1, + "event_id": "4611686018427387905", + "event_name": "Transfer", + "contract_name": "Gravatar", + "block_number": 10861674, + "log_index": 1, + "src_address": "0x2b2f78c5bf6d9c12ee1225d5f374aa91204580c3", + "block_hash": "0xblock1", + "block_timestamp": 1600000000, + "block_fields": { + "number": 10861674 + }, + "transaction_fields": { + "hash": "0xtx1", + "transactionIndex": 0 + }, + "params": { + "to": "0x2", + "from": "0x1", + "value": "9999999999999999999999999999" + }, + "serial": "2" + }, + { + "chain_id": 1, + "event_id": "4611686018427387906", + "event_name": "NewGravatar", + "contract_name": "Gravatar", + "block_number": 10861675, + "log_index": 0, + "src_address": "0x2b2f78c5bf6d9c12ee1225d5f374aa91204580c3", + "block_hash": "0xblock2", + "block_timestamp": 1600000012, + "block_fields": { + "number": 10861675 + }, + "transaction_fields": {}, + "params": { + "id": "1", + "nested": { + "deep": [ + 1, + null, + "x" + ] + }, + "displayName": "unicode 🚀" + }, + "serial": "3" + }, + { + "chain_id": 1337, + "event_id": "1", + "event_name": "EmptyEvent", + "contract_name": "Noop", + "block_number": 1, + "log_index": 0, + "src_address": "0x0000000000000000000000000000000000000000", + "block_hash": "0xblockA", + "block_timestamp": 1500000000, + "block_fields": {}, + "transaction_fields": {}, + "params": {}, + "serial": "4" + }, + { + "chain_id": 1337, + "event_id": "2", + "event_name": "FilterTestEvent", + "contract_name": "EventFiltersTest", + "block_number": 2, + "log_index": 3, + "src_address": "0x4444444444444444444444444444444444444444", + "block_hash": "0xblockB", + "block_timestamp": 1500000060, + "block_fields": { + "extra": true, + "number": 2 + }, + "transaction_fields": { + "hash": null + }, + "params": { + "addr": "0x5555555555555555555555555555555555555555" + }, + "serial": "5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-jsonb-filter.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-jsonb-filter.json new file mode 100644 index 0000000000..2750fa16c1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-jsonb-filter.json @@ -0,0 +1,29 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(where: {params: {_has_key: \"from\"}}, order_by: {serial: asc}) { serial params } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "1", + "params": { + "to": "0x1", + "from": "0x0", + "value": "100" + } + }, + { + "serial": "2", + "params": { + "to": "0x2", + "from": "0x1", + "value": "9999999999999999999999999999" + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-jsonb-path.json b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-jsonb-path.json new file mode 100644 index 0000000000..e7da017779 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/internal-raw-events-jsonb-path.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(where: {event_name: {_eq: \"NewGravatar\"}}) { serial params(path: \"$.nested.deep[0]\") } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "3", + "params": 1 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-admin-query-root.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-admin-query-root.json new file mode 100644 index 0000000000..5ca7b24725 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-admin-query-root.json @@ -0,0 +1,4233 @@ +{ + "role": "admin", + "request": { + "query": "{ __type(name: \"query_root\") { fields { name description args { name description type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } defaultValue } type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "fields": [ + { + "name": "A", + "description": "fetch data from the table: \"A\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A" + } + } + } + } + }, + { + "name": "A_aggregate", + "description": "fetch aggregated fields from the table: \"A\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A_aggregate", + "ofType": null + } + } + }, + { + "name": "A_by_pk", + "description": "fetch data from the table: \"A\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "A", + "ofType": null + } + }, + { + "name": "B", + "description": "fetch data from the table: \"B\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "B_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "B" + } + } + } + } + }, + { + "name": "B_aggregate", + "description": "fetch aggregated fields from the table: \"B\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "B_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "B_aggregate", + "ofType": null + } + } + }, + { + "name": "B_by_pk", + "description": "fetch data from the table: \"B\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "B", + "ofType": null + } + }, + { + "name": "C", + "description": "fetch data from the table: \"C\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "C_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "C" + } + } + } + } + }, + { + "name": "C_aggregate", + "description": "fetch aggregated fields from the table: \"C\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "C_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "C_aggregate", + "ofType": null + } + } + }, + { + "name": "C_by_pk", + "description": "fetch data from the table: \"C\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "C", + "ofType": null + } + }, + { + "name": "CustomSelectionTestPass", + "description": "fetch data from the table: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass" + } + } + } + } + }, + { + "name": "CustomSelectionTestPass_aggregate", + "description": "fetch aggregated fields from the table: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass_aggregate", + "ofType": null + } + } + }, + { + "name": "CustomSelectionTestPass_by_pk", + "description": "fetch data from the table: \"CustomSelectionTestPass\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + } + }, + { + "name": "D", + "description": "fetch data from the table: \"D\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D" + } + } + } + } + }, + { + "name": "D_aggregate", + "description": "fetch aggregated fields from the table: \"D\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D_aggregate", + "ofType": null + } + } + }, + { + "name": "D_by_pk", + "description": "fetch data from the table: \"D\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "D", + "ofType": null + } + }, + { + "name": "EntityWith63LenghtName______________________________________one", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one" + } + } + } + } + }, + { + "name": "EntityWith63LenghtName______________________________________one_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one_aggregate", + "ofType": null + } + } + }, + { + "name": "EntityWith63LenghtName______________________________________one_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + } + }, + { + "name": "EntityWith63LenghtName______________________________________two", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two" + } + } + } + } + }, + { + "name": "EntityWith63LenghtName______________________________________two_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two_aggregate", + "ofType": null + } + } + }, + { + "name": "EntityWith63LenghtName______________________________________two_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + } + }, + { + "name": "EntityWithAllNonArrayTypes", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes" + } + } + } + } + }, + { + "name": "EntityWithAllNonArrayTypes_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes_aggregate", + "ofType": null + } + } + }, + { + "name": "EntityWithAllNonArrayTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + } + }, + { + "name": "EntityWithAllTypes", + "description": "fetch data from the table: \"EntityWithAllTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllTypes" + } + } + } + } + }, + { + "name": "EntityWithAllTypes_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithAllTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllTypes_aggregate", + "ofType": null + } + } + }, + { + "name": "EntityWithAllTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + } + }, + { + "name": "EntityWithBigDecimal", + "description": "fetch data from the table: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal" + } + } + } + } + }, + { + "name": "EntityWithBigDecimal_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal_aggregate", + "ofType": null + } + } + }, + { + "name": "EntityWithBigDecimal_by_pk", + "description": "fetch data from the table: \"EntityWithBigDecimal\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + } + }, + { + "name": "EntityWithRestrictedReScriptField", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField" + } + } + } + } + }, + { + "name": "EntityWithRestrictedReScriptField_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField_aggregate", + "ofType": null + } + } + }, + { + "name": "EntityWithRestrictedReScriptField_by_pk", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + } + }, + { + "name": "EntityWithTimestamp", + "description": "fetch data from the table: \"EntityWithTimestamp\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithTimestamp" + } + } + } + } + }, + { + "name": "EntityWithTimestamp_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithTimestamp\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithTimestamp_aggregate", + "ofType": null + } + } + }, + { + "name": "EntityWithTimestamp_by_pk", + "description": "fetch data from the table: \"EntityWithTimestamp\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + } + }, + { + "name": "Gravatar", + "description": "fetch data from the table: \"Gravatar\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Gravatar_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Gravatar" + } + } + } + } + }, + { + "name": "Gravatar_aggregate", + "description": "fetch aggregated fields from the table: \"Gravatar\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Gravatar_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Gravatar_aggregate", + "ofType": null + } + } + }, + { + "name": "Gravatar_by_pk", + "description": "fetch data from the table: \"Gravatar\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + } + }, + { + "name": "NftCollection", + "description": "fetch data from the table: \"NftCollection\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "NftCollection_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NftCollection" + } + } + } + } + }, + { + "name": "NftCollection_aggregate", + "description": "fetch aggregated fields from the table: \"NftCollection\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "NftCollection_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NftCollection_aggregate", + "ofType": null + } + } + }, + { + "name": "NftCollection_by_pk", + "description": "fetch data from the table: \"NftCollection\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + } + }, + { + "name": "PostgresNumericPrecisionEntityTester", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester" + } + } + } + } + }, + { + "name": "PostgresNumericPrecisionEntityTester_aggregate", + "description": "fetch aggregated fields from the table: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester_aggregate", + "ofType": null + } + } + }, + { + "name": "PostgresNumericPrecisionEntityTester_by_pk", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + } + }, + { + "name": "SimpleEntity", + "description": "fetch data from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity" + } + } + } + } + }, + { + "name": "SimpleEntity_aggregate", + "description": "fetch aggregated fields from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity_aggregate", + "ofType": null + } + } + }, + { + "name": "SimpleEntity_by_pk", + "description": "fetch data from the table: \"SimpleEntity\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + } + }, + { + "name": "SimulateTestEvent", + "description": "fetch data from the table: \"SimulateTestEvent\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimulateTestEvent" + } + } + } + } + }, + { + "name": "SimulateTestEvent_aggregate", + "description": "fetch aggregated fields from the table: \"SimulateTestEvent\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimulateTestEvent_aggregate", + "ofType": null + } + } + }, + { + "name": "SimulateTestEvent_by_pk", + "description": "fetch data from the table: \"SimulateTestEvent\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + } + }, + { + "name": "Token", + "description": "fetch data from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token" + } + } + } + } + }, + { + "name": "Token_aggregate", + "description": "fetch aggregated fields from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token_aggregate", + "ofType": null + } + } + }, + { + "name": "Token_by_pk", + "description": "fetch data from the table: \"Token\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + }, + { + "name": "User", + "description": "fetch data from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User" + } + } + } + } + }, + { + "name": "User_aggregate", + "description": "fetch aggregated fields from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User_aggregate", + "ofType": null + } + } + }, + { + "name": "User_by_pk", + "description": "fetch data from the table: \"User\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + } + }, + { + "name": "_meta", + "description": "fetch data from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta" + } + } + } + } + }, + { + "name": "_meta_aggregate", + "description": "fetch aggregated fields from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta_aggregate", + "ofType": null + } + } + }, + { + "name": "chain_metadata", + "description": "fetch data from the table: \"chain_metadata\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "chain_metadata" + } + } + } + } + }, + { + "name": "chain_metadata_aggregate", + "description": "fetch aggregated fields from the table: \"chain_metadata\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "chain_metadata_aggregate", + "ofType": null + } + } + }, + { + "name": "raw_events", + "description": "fetch data from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events" + } + } + } + } + }, + { + "name": "raw_events_aggregate", + "description": "fetch aggregated fields from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events_aggregate", + "ofType": null + } + } + }, + { + "name": "raw_events_by_pk", + "description": "fetch data from the table: \"raw_events\" using primary key columns", + "args": [ + { + "name": "serial", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-admin-subscription-root.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-admin-subscription-root.json new file mode 100644 index 0000000000..028dbdb090 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-admin-subscription-root.json @@ -0,0 +1,4371 @@ +{ + "role": "admin", + "request": { + "query": "{ __type(name: \"subscription_root\") { fields { name description args { name type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } type { kind name } } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "fields": [ + { + "name": "A", + "description": "fetch data from the table: \"A\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "A_aggregate", + "description": "fetch aggregated fields from the table: \"A\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "A_by_pk", + "description": "fetch data from the table: \"A\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "A" + } + }, + { + "name": "A_stream", + "description": "fetch data from the table in a streaming manner: \"A\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "B", + "description": "fetch data from the table: \"B\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "B_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "B_aggregate", + "description": "fetch aggregated fields from the table: \"B\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "B_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "B_by_pk", + "description": "fetch data from the table: \"B\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "B" + } + }, + { + "name": "B_stream", + "description": "fetch data from the table in a streaming manner: \"B\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "C", + "description": "fetch data from the table: \"C\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "C_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "C_aggregate", + "description": "fetch aggregated fields from the table: \"C\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "C_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "C_by_pk", + "description": "fetch data from the table: \"C\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "C" + } + }, + { + "name": "C_stream", + "description": "fetch data from the table in a streaming manner: \"C\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "CustomSelectionTestPass", + "description": "fetch data from the table: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "CustomSelectionTestPass_aggregate", + "description": "fetch aggregated fields from the table: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "CustomSelectionTestPass_by_pk", + "description": "fetch data from the table: \"CustomSelectionTestPass\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass" + } + }, + { + "name": "CustomSelectionTestPass_stream", + "description": "fetch data from the table in a streaming manner: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "D", + "description": "fetch data from the table: \"D\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "D_aggregate", + "description": "fetch aggregated fields from the table: \"D\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "D_by_pk", + "description": "fetch data from the table: \"D\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "D" + } + }, + { + "name": "D_stream", + "description": "fetch data from the table in a streaming manner: \"D\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWith63LenghtName______________________________________one", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWith63LenghtName______________________________________one_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWith63LenghtName______________________________________one_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one" + } + }, + { + "name": "EntityWith63LenghtName______________________________________one_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWith63LenghtName______________________________________two", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWith63LenghtName______________________________________two_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWith63LenghtName______________________________________two_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two" + } + }, + { + "name": "EntityWith63LenghtName______________________________________two_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithAllNonArrayTypes", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithAllNonArrayTypes_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithAllNonArrayTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes" + } + }, + { + "name": "EntityWithAllNonArrayTypes_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithAllTypes", + "description": "fetch data from the table: \"EntityWithAllTypes\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithAllTypes_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithAllTypes\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithAllTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllTypes\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllTypes" + } + }, + { + "name": "EntityWithAllTypes_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithAllTypes\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithBigDecimal", + "description": "fetch data from the table: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithBigDecimal_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithBigDecimal_by_pk", + "description": "fetch data from the table: \"EntityWithBigDecimal\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal" + } + }, + { + "name": "EntityWithBigDecimal_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithRestrictedReScriptField", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithRestrictedReScriptField_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithRestrictedReScriptField_by_pk", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField" + } + }, + { + "name": "EntityWithRestrictedReScriptField_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithTimestamp", + "description": "fetch data from the table: \"EntityWithTimestamp\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithTimestamp_aggregate", + "description": "fetch aggregated fields from the table: \"EntityWithTimestamp\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "EntityWithTimestamp_by_pk", + "description": "fetch data from the table: \"EntityWithTimestamp\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithTimestamp" + } + }, + { + "name": "EntityWithTimestamp_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithTimestamp\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "Gravatar", + "description": "fetch data from the table: \"Gravatar\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Gravatar_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "Gravatar_aggregate", + "description": "fetch aggregated fields from the table: \"Gravatar\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Gravatar_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "Gravatar_by_pk", + "description": "fetch data from the table: \"Gravatar\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "Gravatar" + } + }, + { + "name": "Gravatar_stream", + "description": "fetch data from the table in a streaming manner: \"Gravatar\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "NftCollection", + "description": "fetch data from the table: \"NftCollection\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "NftCollection_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "NftCollection_aggregate", + "description": "fetch aggregated fields from the table: \"NftCollection\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "NftCollection_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "NftCollection_by_pk", + "description": "fetch data from the table: \"NftCollection\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "NftCollection" + } + }, + { + "name": "NftCollection_stream", + "description": "fetch data from the table in a streaming manner: \"NftCollection\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "PostgresNumericPrecisionEntityTester", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "PostgresNumericPrecisionEntityTester_aggregate", + "description": "fetch aggregated fields from the table: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "PostgresNumericPrecisionEntityTester_by_pk", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester" + } + }, + { + "name": "PostgresNumericPrecisionEntityTester_stream", + "description": "fetch data from the table in a streaming manner: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "SimpleEntity", + "description": "fetch data from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "SimpleEntity_aggregate", + "description": "fetch aggregated fields from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "SimpleEntity_by_pk", + "description": "fetch data from the table: \"SimpleEntity\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "SimpleEntity" + } + }, + { + "name": "SimpleEntity_stream", + "description": "fetch data from the table in a streaming manner: \"SimpleEntity\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "SimulateTestEvent", + "description": "fetch data from the table: \"SimulateTestEvent\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "SimulateTestEvent_aggregate", + "description": "fetch aggregated fields from the table: \"SimulateTestEvent\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "SimulateTestEvent_by_pk", + "description": "fetch data from the table: \"SimulateTestEvent\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "SimulateTestEvent" + } + }, + { + "name": "SimulateTestEvent_stream", + "description": "fetch data from the table in a streaming manner: \"SimulateTestEvent\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "Token", + "description": "fetch data from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "Token_aggregate", + "description": "fetch aggregated fields from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "Token_by_pk", + "description": "fetch data from the table: \"Token\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "Token" + } + }, + { + "name": "Token_stream", + "description": "fetch data from the table in a streaming manner: \"Token\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "User", + "description": "fetch data from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "User_aggregate", + "description": "fetch aggregated fields from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "User_by_pk", + "description": "fetch data from the table: \"User\" using primary key columns", + "args": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "User" + } + }, + { + "name": "User_stream", + "description": "fetch data from the table in a streaming manner: \"User\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "_meta", + "description": "fetch data from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "_meta_aggregate", + "description": "fetch aggregated fields from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "_meta_stream", + "description": "fetch data from the table in a streaming manner: \"_meta\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "chain_metadata", + "description": "fetch data from the table: \"chain_metadata\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "chain_metadata_aggregate", + "description": "fetch aggregated fields from the table: \"chain_metadata\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "chain_metadata_stream", + "description": "fetch data from the table in a streaming manner: \"chain_metadata\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "raw_events", + "description": "fetch data from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "raw_events_aggregate", + "description": "fetch aggregated fields from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + } + }, + { + "name": "limit", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "offset", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "name": "order_by", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + }, + { + "name": "raw_events_by_pk", + "description": "fetch data from the table: \"raw_events\" using primary key columns", + "args": [ + { + "name": "serial", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + } + } + ], + "type": { + "kind": "OBJECT", + "name": "raw_events" + } + }, + { + "name": "raw_events_stream", + "description": "fetch data from the table in a streaming manner: \"raw_events\"", + "args": [ + { + "name": "batch_size", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_stream_cursor_input", + "ofType": null + } + } + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-aggregate-types-admin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-aggregate-types-admin.json new file mode 100644 index 0000000000..0884347c7c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-aggregate-types-admin.json @@ -0,0 +1,149 @@ +{ + "role": "admin", + "request": { + "query": "{ agg: __type(name: \"Token_aggregate_fields\") { fields { name args { name defaultValue type { kind name ofType { kind name } } } type { kind name ofType { kind name } } } } sum: __type(name: \"Token_sum_fields\") { fields { name type { name } } } }" + }, + "status": 200, + "body": { + "data": { + "agg": { + "fields": [ + { + "name": "avg", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_avg_fields", + "ofType": null + } + }, + { + "name": "count", + "args": [ + { + "name": "columns", + "defaultValue": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null + } + } + }, + { + "name": "distinct", + "defaultValue": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + } + }, + { + "name": "max", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_max_fields", + "ofType": null + } + }, + { + "name": "min", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_min_fields", + "ofType": null + } + }, + { + "name": "stddev", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_stddev_fields", + "ofType": null + } + }, + { + "name": "stddev_pop", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_stddev_pop_fields", + "ofType": null + } + }, + { + "name": "stddev_samp", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_stddev_samp_fields", + "ofType": null + } + }, + { + "name": "sum", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_sum_fields", + "ofType": null + } + }, + { + "name": "var_pop", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_var_pop_fields", + "ofType": null + } + }, + { + "name": "var_samp", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_var_samp_fields", + "ofType": null + } + }, + { + "name": "variance", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_variance_fields", + "ofType": null + } + } + ] + }, + "sum": { + "fields": [ + { + "name": "tokenId", + "type": { + "name": "numeric" + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-aggregate-types-hidden-public.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-aggregate-types-hidden-public.json new file mode 100644 index 0000000000..627ebd3d45 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-aggregate-types-hidden-public.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"Token_aggregate_fields\") { name } }" + }, + "status": 200, + "body": { + "data": { + "__type": null + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-deprecated-flag.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-deprecated-flag.json new file mode 100644 index 0000000000..1aea0aeee9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-deprecated-flag.json @@ -0,0 +1,183 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"query_root\") { fields(includeDeprecated: true) { name isDeprecated } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "fields": [ + { + "name": "A", + "isDeprecated": false + }, + { + "name": "A_by_pk", + "isDeprecated": false + }, + { + "name": "B", + "isDeprecated": false + }, + { + "name": "B_by_pk", + "isDeprecated": false + }, + { + "name": "C", + "isDeprecated": false + }, + { + "name": "C_by_pk", + "isDeprecated": false + }, + { + "name": "CustomSelectionTestPass", + "isDeprecated": false + }, + { + "name": "CustomSelectionTestPass_by_pk", + "isDeprecated": false + }, + { + "name": "D", + "isDeprecated": false + }, + { + "name": "D_by_pk", + "isDeprecated": false + }, + { + "name": "EntityWith63LenghtName______________________________________one", + "isDeprecated": false + }, + { + "name": "EntityWith63LenghtName______________________________________one_by_pk", + "isDeprecated": false + }, + { + "name": "EntityWith63LenghtName______________________________________two", + "isDeprecated": false + }, + { + "name": "EntityWith63LenghtName______________________________________two_by_pk", + "isDeprecated": false + }, + { + "name": "EntityWithAllNonArrayTypes", + "isDeprecated": false + }, + { + "name": "EntityWithAllNonArrayTypes_by_pk", + "isDeprecated": false + }, + { + "name": "EntityWithAllTypes", + "isDeprecated": false + }, + { + "name": "EntityWithAllTypes_by_pk", + "isDeprecated": false + }, + { + "name": "EntityWithBigDecimal", + "isDeprecated": false + }, + { + "name": "EntityWithBigDecimal_by_pk", + "isDeprecated": false + }, + { + "name": "EntityWithRestrictedReScriptField", + "isDeprecated": false + }, + { + "name": "EntityWithRestrictedReScriptField_by_pk", + "isDeprecated": false + }, + { + "name": "EntityWithTimestamp", + "isDeprecated": false + }, + { + "name": "EntityWithTimestamp_by_pk", + "isDeprecated": false + }, + { + "name": "Gravatar", + "isDeprecated": false + }, + { + "name": "Gravatar_by_pk", + "isDeprecated": false + }, + { + "name": "NftCollection", + "isDeprecated": false + }, + { + "name": "NftCollection_by_pk", + "isDeprecated": false + }, + { + "name": "PostgresNumericPrecisionEntityTester", + "isDeprecated": false + }, + { + "name": "PostgresNumericPrecisionEntityTester_by_pk", + "isDeprecated": false + }, + { + "name": "SimpleEntity", + "isDeprecated": false + }, + { + "name": "SimpleEntity_by_pk", + "isDeprecated": false + }, + { + "name": "SimulateTestEvent", + "isDeprecated": false + }, + { + "name": "SimulateTestEvent_by_pk", + "isDeprecated": false + }, + { + "name": "Token", + "isDeprecated": false + }, + { + "name": "Token_by_pk", + "isDeprecated": false + }, + { + "name": "User", + "isDeprecated": false + }, + { + "name": "User_by_pk", + "isDeprecated": false + }, + { + "name": "_meta", + "isDeprecated": false + }, + { + "name": "chain_metadata", + "isDeprecated": false + }, + { + "name": "raw_events", + "isDeprecated": false + }, + { + "name": "raw_events_by_pk", + "isDeprecated": false + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-descriptions-bool-exp-and-order-by.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-descriptions-bool-exp-and-order-by.json new file mode 100644 index 0000000000..fb501cd7dc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-descriptions-bool-exp-and-order-by.json @@ -0,0 +1,87 @@ +{ + "role": "public", + "request": { + "query": "{ bool_exp: __type(name: \"User_bool_exp\") { inputFields { name description } } order_by: __type(name: \"User_order_by\") { inputFields { name description } } }" + }, + "status": 200, + "body": { + "data": { + "bool_exp": { + "inputFields": [ + { + "name": "_and", + "description": null + }, + { + "name": "_not", + "description": null + }, + { + "name": "_or", + "description": null + }, + { + "name": "accountType", + "description": null + }, + { + "name": "address", + "description": null + }, + { + "name": "gravatar", + "description": null + }, + { + "name": "gravatar_id", + "description": null + }, + { + "name": "id", + "description": null + }, + { + "name": "tokens", + "description": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null + } + ] + }, + "order_by": { + "inputFields": [ + { + "name": "accountType", + "description": null + }, + { + "name": "address", + "description": null + }, + { + "name": "gravatar", + "description": null + }, + { + "name": "gravatar_id", + "description": null + }, + { + "name": "id", + "description": null + }, + { + "name": "tokens_aggregate", + "description": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-descriptions-stream-cursor-value-input.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-descriptions-stream-cursor-value-input.json new file mode 100644 index 0000000000..f6e37ac17e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-descriptions-stream-cursor-value-input.json @@ -0,0 +1,35 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"User_stream_cursor_value_input\") { inputFields { name description } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "inputFields": [ + { + "name": "accountType", + "description": null + }, + { + "name": "address", + "description": "The user's wallet address, lowercased." + }, + { + "name": "gravatar_id", + "description": null + }, + { + "name": "id", + "description": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-descriptions.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-descriptions.json new file mode 100644 index 0000000000..df2cfb903d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-descriptions.json @@ -0,0 +1,44 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"User\") { description fields { name description } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "description": "A user of the protocol, keyed by their wallet address.", + "fields": [ + { + "name": "accountType", + "description": null + }, + { + "name": "address", + "description": "The user's wallet address, lowercased." + }, + { + "name": "gravatar", + "description": "An object relationship" + }, + { + "name": "gravatar_id", + "description": null + }, + { + "name": "id", + "description": null + }, + { + "name": "tokens", + "description": "An array relationship" + }, + { + "name": "updatesCountOnUserForTesting", + "description": null + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-full-public.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-full-public.json new file mode 100644 index 0000000000..1a368ac3ef --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-full-public.json @@ -0,0 +1,21007 @@ +{ + "role": "public", + "request": { + "query": "\nquery IntrospectionQuery {\n __schema {\n queryType { name }\n mutationType { name }\n subscriptionType { name }\n types { ...FullType }\n directives { name description locations args { ...InputValue } }\n }\n}\nfragment FullType on __Type {\n kind name description\n fields(includeDeprecated: true) {\n name description\n args { ...InputValue }\n type { ...TypeRef }\n isDeprecated deprecationReason\n }\n inputFields { ...InputValue }\n interfaces { ...TypeRef }\n enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason }\n possibleTypes { ...TypeRef }\n}\nfragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue }\nfragment TypeRef on __Type {\n kind name\n ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } }\n}" + }, + "status": 200, + "body": { + "data": { + "__schema": { + "queryType": { + "name": "query_root" + }, + "mutationType": null, + "subscriptionType": { + "name": "subscription_root" + }, + "types": [ + { + "kind": "OBJECT", + "name": "A", + "description": "columns and relationships of \"A\"", + "fields": [ + { + "name": "b", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "B", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "b_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_aggregate_order_by", + "description": "order by aggregate values of table \"A\"", + "fields": null, + "inputFields": [ + { + "name": "count", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "max", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_max_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "min", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_min_order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "description": "Boolean expression to filter rows from the table \"A\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "b", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "b_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_max_order_by", + "description": "order by max() on columns of table \"A\"", + "fields": null, + "inputFields": [ + { + "name": "b_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_min_order_by", + "description": "order by min() on columns of table \"A\"", + "fields": null, + "inputFields": [ + { + "name": "b_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "description": "Ordering options when selecting data from \"A\".", + "fields": null, + "inputFields": [ + { + "name": "b", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "b_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "A_select_column", + "description": "select columns of table \"A\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "b_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_stream_cursor_input", + "description": "Streaming cursor of the table \"A\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "b_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "B", + "description": "columns and relationships of \"B\"", + "fields": [ + { + "name": "a", + "description": "An array relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "c", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "C", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "c_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "description": "Boolean expression to filter rows from the table \"B\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "a", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "c", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "c_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "description": "Ordering options when selecting data from \"B\".", + "fields": null, + "inputFields": [ + { + "name": "a_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_aggregate_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "c", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "c_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "B_select_column", + "description": "select columns of table \"B\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "c_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "B_stream_cursor_input", + "description": "Streaming cursor of the table \"B\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "B_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "c_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "Boolean", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "description": "Boolean expression to compare columns of type \"Boolean\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "C", + "description": "columns and relationships of \"C\"", + "fields": [ + { + "name": "a", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "A", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "a_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "d", + "description": "An array relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stringThatIsMirroredToA", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "description": "Boolean expression to filter rows from the table \"C\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "a", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "a_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "d", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stringThatIsMirroredToA", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "description": "Ordering options when selecting data from \"C\".", + "fields": null, + "inputFields": [ + { + "name": "a", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "a_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "d_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_aggregate_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stringThatIsMirroredToA", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "C_select_column", + "description": "select columns of table \"C\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "a_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stringThatIsMirroredToA", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "C_stream_cursor_input", + "description": "Streaming cursor of the table \"C\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "C_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "a_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stringThatIsMirroredToA", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "description": "columns and relationships of \"CustomSelectionTestPass\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "description": "Boolean expression to filter rows from the table \"CustomSelectionTestPass\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "description": "Ordering options when selecting data from \"CustomSelectionTestPass\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "description": "select columns of table \"CustomSelectionTestPass\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_stream_cursor_input", + "description": "Streaming cursor of the table \"CustomSelectionTestPass\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "D", + "description": "columns and relationships of \"D\"", + "fields": [ + { + "name": "c", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_aggregate_order_by", + "description": "order by aggregate values of table \"D\"", + "fields": null, + "inputFields": [ + { + "name": "count", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "max", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_max_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "min", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_min_order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "description": "Boolean expression to filter rows from the table \"D\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "c", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_max_order_by", + "description": "order by max() on columns of table \"D\"", + "fields": null, + "inputFields": [ + { + "name": "c", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_min_order_by", + "description": "order by min() on columns of table \"D\"", + "fields": null, + "inputFields": [ + { + "name": "c", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "description": "Ordering options when selecting data from \"D\".", + "fields": null, + "inputFields": [ + { + "name": "c", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "D_select_column", + "description": "select columns of table \"D\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "c", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_stream_cursor_input", + "description": "Streaming cursor of the table \"D\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "c", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "description": "columns and relationships of \"EntityWith63LenghtName______________________________________one\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWith63LenghtName______________________________________one\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "description": "Ordering options when selecting data from \"EntityWith63LenghtName______________________________________one\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "description": "select columns of table \"EntityWith63LenghtName______________________________________one\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWith63LenghtName______________________________________one\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "description": "columns and relationships of \"EntityWith63LenghtName______________________________________two\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWith63LenghtName______________________________________two\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "description": "Ordering options when selecting data from \"EntityWith63LenghtName______________________________________two\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "description": "select columns of table \"EntityWith63LenghtName______________________________________two\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWith63LenghtName______________________________________two\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "description": "columns and relationships of \"EntityWithAllNonArrayTypes\"", + "fields": [ + { + "name": "bigDecimal", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigInt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bool", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumField", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "float_", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "int_", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigDecimal", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBool", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optEnumField", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optFloat", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optString", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optTimestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "string", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithAllNonArrayTypes\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "description": "Ordering options when selecting data from \"EntityWithAllNonArrayTypes\".", + "fields": null, + "inputFields": [ + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "description": "select columns of table \"EntityWithAllNonArrayTypes\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "bigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimalWithConfig", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bool", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumField", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "float_", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "int_", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBool", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optEnumField", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optFloat", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optString", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optTimestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "string", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithAllNonArrayTypes\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "description": "columns and relationships of \"EntityWithAllTypes\"", + "fields": [ + { + "name": "arrayOfBigDecimals", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfBigInts", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfFloats", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfInts", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfStrings", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimal", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigInt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bool", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumField", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "float_", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "int_", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "json", + "description": null, + "args": [ + { + "name": "path", + "description": "JSON select path", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigDecimal", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBool", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optEnumField", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optFloat", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optString", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optTimestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "string", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithAllTypes\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfBigDecimals", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfBigInts", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfFloats", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfInts", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfStrings", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "json", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "description": "Ordering options when selecting data from \"EntityWithAllTypes\".", + "fields": null, + "inputFields": [ + { + "name": "arrayOfBigDecimals", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfBigInts", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfFloats", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfInts", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfStrings", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "json", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "description": "select columns of table \"EntityWithAllTypes\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "arrayOfBigDecimals", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfBigInts", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfFloats", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfInts", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfStrings", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimalWithConfig", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bool", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumField", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "float_", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "int_", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "json", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBool", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optEnumField", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optFloat", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optString", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optTimestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "string", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithAllTypes\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "arrayOfBigDecimals", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfBigInts", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfFloats", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfInts", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfStrings", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "json", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "description": "columns and relationships of \"EntityWithBigDecimal\"", + "fields": [ + { + "name": "bigDecimal", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithBigDecimal\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "description": "Ordering options when selecting data from \"EntityWithBigDecimal\".", + "fields": null, + "inputFields": [ + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "description": "select columns of table \"EntityWithBigDecimal\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "bigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithBigDecimal\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "description": "columns and relationships of \"EntityWithRestrictedReScriptField\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithRestrictedReScriptField\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "description": "Ordering options when selecting data from \"EntityWithRestrictedReScriptField\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "description": "select columns of table \"EntityWithRestrictedReScriptField\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithRestrictedReScriptField\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "description": "columns and relationships of \"EntityWithTimestamp\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithTimestamp\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "description": "Ordering options when selecting data from \"EntityWithTimestamp\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "description": "select columns of table \"EntityWithTimestamp\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithTimestamp\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "Float", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Float_comparison_exp", + "description": "Boolean expression to compare columns of type \"Float\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Gravatar", + "description": "columns and relationships of \"Gravatar\"", + "fields": [ + { + "name": "displayName", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "imageUrl", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "size", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCount", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "description": "Boolean expression to filter rows from the table \"Gravatar\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "displayName", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "imageUrl", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "size", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "gravatarsize_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCount", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "description": "Ordering options when selecting data from \"Gravatar\".", + "fields": null, + "inputFields": [ + { + "name": "displayName", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "imageUrl", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "size", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCount", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "Gravatar_select_column", + "description": "select columns of table \"Gravatar\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "displayName", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "imageUrl", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "size", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCount", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Gravatar_stream_cursor_input", + "description": "Streaming cursor of the table \"Gravatar\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Gravatar_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "displayName", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "imageUrl", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "size", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCount", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "Int", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Int_array_comparison_exp", + "description": "Boolean expression to compare columns of type \"Int\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_contained_in", + "description": "is the array contained in the given array value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the array contain the given value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "description": "Boolean expression to compare columns of type \"Int\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "NftCollection", + "description": "columns and relationships of \"NftCollection\"", + "fields": [ + { + "name": "contractAddress", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "currentSupply", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "maxSupply", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "symbol", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokens", + "description": "An array relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "description": "Boolean expression to filter rows from the table \"NftCollection\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "contractAddress", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "currentSupply", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "maxSupply", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "name", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "symbol", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "description": "Ordering options when selecting data from \"NftCollection\".", + "fields": null, + "inputFields": [ + { + "name": "contractAddress", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "currentSupply", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "maxSupply", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "name", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "symbol", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "NftCollection_select_column", + "description": "select columns of table \"NftCollection\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "contractAddress", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "currentSupply", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "maxSupply", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "symbol", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NftCollection_stream_cursor_input", + "description": "Streaming cursor of the table \"NftCollection\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NftCollection_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "contractAddress", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "currentSupply", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "maxSupply", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "name", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "symbol", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "description": "columns and relationships of \"PostgresNumericPrecisionEntityTester\"", + "fields": [ + { + "name": "exampleBigDecimal", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalArray", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalRequired", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntArray", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntRequired", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "description": "Boolean expression to filter rows from the table \"PostgresNumericPrecisionEntityTester\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArray", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalRequired", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArray", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntRequired", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "description": "Ordering options when selecting data from \"PostgresNumericPrecisionEntityTester\".", + "fields": null, + "inputFields": [ + { + "name": "exampleBigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArray", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalRequired", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArray", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntRequired", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "description": "select columns of table \"PostgresNumericPrecisionEntityTester\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "exampleBigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalArray", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalRequired", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntArray", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntRequired", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_stream_cursor_input", + "description": "Streaming cursor of the table \"PostgresNumericPrecisionEntityTester\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "exampleBigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArray", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalRequired", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArray", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigIntRequired", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SimpleEntity", + "description": "columns and relationships of \"SimpleEntity\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "value", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "description": "Boolean expression to filter rows from the table \"SimpleEntity\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "value", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "description": "Ordering options when selecting data from \"SimpleEntity\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "value", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "description": "select columns of table \"SimpleEntity\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "value", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_stream_cursor_input", + "description": "Streaming cursor of the table \"SimpleEntity\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "value", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "description": "columns and relationships of \"SimulateTestEvent\"", + "fields": [ + { + "name": "blockNumber", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "logIndex", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "description": "Boolean expression to filter rows from the table \"SimulateTestEvent\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "blockNumber", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "logIndex", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "description": "Ordering options when selecting data from \"SimulateTestEvent\".", + "fields": null, + "inputFields": [ + { + "name": "blockNumber", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "logIndex", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "description": "select columns of table \"SimulateTestEvent\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "blockNumber", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "logIndex", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_stream_cursor_input", + "description": "Streaming cursor of the table \"SimulateTestEvent\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "blockNumber", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "logIndex", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "String", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "String_array_comparison_exp", + "description": "Boolean expression to compare columns of type \"String\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_contained_in", + "description": "is the array contained in the given array value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the array contain the given value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "description": "Boolean expression to compare columns of type \"String\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_ilike", + "description": "does the column match the given case-insensitive pattern", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_iregex", + "description": "does the column match the given POSIX regular expression, case insensitive", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_like", + "description": "does the column match the given pattern", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nilike", + "description": "does the column NOT match the given case-insensitive pattern", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_niregex", + "description": "does the column NOT match the given POSIX regular expression, case insensitive", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nlike", + "description": "does the column NOT match the given pattern", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nregex", + "description": "does the column NOT match the given POSIX regular expression, case sensitive", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nsimilar", + "description": "does the column NOT match the given SQL regular expression", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_regex", + "description": "does the column match the given POSIX regular expression, case sensitive", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_similar", + "description": "does the column match the given SQL regular expression", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token", + "description": "columns and relationships of \"Token\"", + "fields": [ + { + "name": "collection", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "collection_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_order_by", + "description": "order by aggregate values of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "avg", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_avg_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "count", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "max", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_max_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "min", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_min_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stddev", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stddev_pop", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_pop_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stddev_samp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_samp_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sum", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_sum_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "var_pop", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_var_pop_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "var_samp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_var_samp_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "variance", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_variance_order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_avg_order_by", + "description": "order by avg() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "description": "Boolean expression to filter rows from the table \"Token\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "collection", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "collection_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_max_order_by", + "description": "order by max() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "collection_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_min_order_by", + "description": "order by min() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "collection_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "description": "Ordering options when selecting data from \"Token\".", + "fields": null, + "inputFields": [ + { + "name": "collection", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "collection_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "Token_select_column", + "description": "select columns of table \"Token\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "collection_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokenId", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_order_by", + "description": "order by stddev() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_pop_order_by", + "description": "order by stddev_pop() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_samp_order_by", + "description": "order by stddev_samp() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stream_cursor_input", + "description": "Streaming cursor of the table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "collection_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_sum_order_by", + "description": "order by sum() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_var_pop_order_by", + "description": "order by var_pop() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_var_samp_order_by", + "description": "order by var_samp() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_variance_order_by", + "description": "order by variance() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User", + "description": "A user of the protocol, keyed by their wallet address.", + "fields": [ + { + "name": "accountType", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "address", + "description": "The user's wallet address, lowercased.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gravatar", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gravatar_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokens", + "description": "An array relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "description": "Boolean expression to filter rows from the table \"User\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "accountType", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "address", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "description": "Ordering options when selecting data from \"User\".", + "fields": null, + "inputFields": [ + { + "name": "accountType", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "address", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "User_select_column", + "description": "select columns of table \"User\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "accountType", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "address", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gravatar_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_input", + "description": "Streaming cursor of the table \"User\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "accountType", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "address", + "description": "The user's wallet address, lowercased.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__Directive", + "description": null, + "fields": [ + { + "name": "args", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__InputValue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isRepeatable", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "locations", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__EnumValue", + "description": null, + "fields": [ + { + "name": "deprecationReason", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isDeprecated", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__Field", + "description": null, + "fields": [ + { + "name": "args", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__InputValue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "deprecationReason", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isDeprecated", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__InputValue", + "description": null, + "fields": [ + { + "name": "defaultValue", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__Schema", + "description": null, + "fields": [ + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "directives", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Directive", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "mutationType", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "queryType", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "subscriptionType", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "types", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__Type", + "description": null, + "fields": [ + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumValues", + "description": null, + "args": [ + { + "name": "includeDeprecated", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": "false" + } + ], + "type": { + "kind": "OBJECT", + "name": "__EnumValue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "fields", + "description": null, + "args": [ + { + "name": "includeDeprecated", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": "false" + } + ], + "type": { + "kind": "OBJECT", + "name": "__Field", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "inputFields", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__InputValue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "interfaces", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "kind", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "__TypeKind", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "ofType", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "possibleTypes", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "__TypeKind", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ENUM", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "INPUT_OBJECT", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "INTERFACE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "LIST", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NON_NULL", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "OBJECT", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SCALAR", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "UNION", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta", + "description": "columns and relationships of \"_meta\"", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isReady", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "readyAt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "description": "Boolean expression to filter rows from the table \"_meta\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "bufferBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chainId", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "eventsProcessed", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Float_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "firstEventBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "isReady", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "progressBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "readyAt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sourceBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "description": "Ordering options when selecting data from \"_meta\".", + "fields": null, + "inputFields": [ + { + "name": "bufferBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chainId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "eventsProcessed", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "firstEventBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "isReady", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "progressBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "readyAt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sourceBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "_meta_select_column", + "description": "select columns of table \"_meta\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "bufferBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isReady", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "readyAt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "_meta_stream_cursor_input", + "description": "Streaming cursor of the table \"_meta\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "_meta_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "bufferBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chainId", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "eventsProcessed", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "firstEventBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "isReady", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "progressBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "readyAt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sourceBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "accounttype", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "description": "Boolean expression to compare columns of type \"accounttype\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "bigint", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "bigint_comparison_exp", + "description": "Boolean expression to compare columns of type \"bigint\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "chain_metadata", + "description": "columns and relationships of \"chain_metadata\"", + "fields": [ + { + "name": "block_height", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "end_block", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "first_event_block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "is_hyper_sync", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "latest_fetched_block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "latest_processed_block", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "num_batches_fetched", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "num_events_processed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "start_block", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "description": "Boolean expression to filter rows from the table \"chain_metadata\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "block_height", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "end_block", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first_event_block_number", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "is_hyper_sync", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_fetched_block_number", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_processed_block", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_batches_fetched", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_events_processed", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Float_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "start_block", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "description": "Ordering options when selecting data from \"chain_metadata\".", + "fields": null, + "inputFields": [ + { + "name": "block_height", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "end_block", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first_event_block_number", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "is_hyper_sync", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_fetched_block_number", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_processed_block", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_batches_fetched", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_events_processed", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "start_block", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "description": "select columns of table \"chain_metadata\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "block_height", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "end_block", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "first_event_block_number", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "is_hyper_sync", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "latest_fetched_block_number", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "latest_processed_block", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "num_batches_fetched", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "num_events_processed", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "start_block", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_stream_cursor_input", + "description": "Streaming cursor of the table \"chain_metadata\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "block_height", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "end_block", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first_event_block_number", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "is_hyper_sync", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_fetched_block_number", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_processed_block", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_batches_fetched", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_events_processed", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "start_block", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "cursor_ordering", + "description": "ordering argument of a cursor", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ASC", + "description": "ascending ordering of the cursor", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "DESC", + "description": "descending ordering of the cursor", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "float8", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "float8_array_comparison_exp", + "description": "Boolean expression to compare columns of type \"float8\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_contained_in", + "description": "is the array contained in the given array value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the array contain the given value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "description": "Boolean expression to compare columns of type \"float8\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "gravatarsize", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "gravatarsize_comparison_exp", + "description": "Boolean expression to compare columns of type \"gravatarsize\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "jsonb", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "jsonb_cast_exp", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "String", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "description": "Boolean expression to compare columns of type \"jsonb\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_cast", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_cast_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_contained_in", + "description": "is the column contained in the given json value", + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the column contain the given json value at the top level", + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_has_key", + "description": "does the string exist as a top-level key in the column", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_has_keys_all", + "description": "do all of these strings exist as top-level keys in the column", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_has_keys_any", + "description": "do any of these strings exist as top-level keys in the column", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "numeric", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "description": "Boolean expression to compare columns of type \"numeric\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_contained_in", + "description": "is the array contained in the given array value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the array contain the given value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "description": "Boolean expression to compare columns of type \"numeric\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "order_by", + "description": "column ordering options", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "asc", + "description": "in ascending order, nulls last", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "asc_nulls_first", + "description": "in ascending order, nulls first", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "asc_nulls_last", + "description": "in ascending order, nulls last", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "desc", + "description": "in descending order, nulls first", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "desc_nulls_first", + "description": "in descending order, nulls first", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "desc_nulls_last", + "description": "in descending order, nulls last", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "query_root", + "description": null, + "fields": [ + { + "name": "A", + "description": "fetch data from the table: \"A\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "A_by_pk", + "description": "fetch data from the table: \"A\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "A", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B", + "description": "fetch data from the table: \"B\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "B_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "B", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B_by_pk", + "description": "fetch data from the table: \"B\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "B", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C", + "description": "fetch data from the table: \"C\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "C_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "C", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C_by_pk", + "description": "fetch data from the table: \"C\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "C", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass", + "description": "fetch data from the table: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass_by_pk", + "description": "fetch data from the table: \"CustomSelectionTestPass\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D", + "description": "fetch data from the table: \"D\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D_by_pk", + "description": "fetch data from the table: \"D\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "D", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes", + "description": "fetch data from the table: \"EntityWithAllTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal", + "description": "fetch data from the table: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal_by_pk", + "description": "fetch data from the table: \"EntityWithBigDecimal\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField_by_pk", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp", + "description": "fetch data from the table: \"EntityWithTimestamp\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp_by_pk", + "description": "fetch data from the table: \"EntityWithTimestamp\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar", + "description": "fetch data from the table: \"Gravatar\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Gravatar_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar_by_pk", + "description": "fetch data from the table: \"Gravatar\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection", + "description": "fetch data from the table: \"NftCollection\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "NftCollection_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection_by_pk", + "description": "fetch data from the table: \"NftCollection\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester_by_pk", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity", + "description": "fetch data from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity_by_pk", + "description": "fetch data from the table: \"SimpleEntity\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent", + "description": "fetch data from the table: \"SimulateTestEvent\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent_by_pk", + "description": "fetch data from the table: \"SimulateTestEvent\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token", + "description": "fetch data from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token_by_pk", + "description": "fetch data from the table: \"Token\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User", + "description": "fetch data from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User_by_pk", + "description": "fetch data from the table: \"User\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "_meta", + "description": "fetch data from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_metadata", + "description": "fetch data from the table: \"chain_metadata\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "chain_metadata", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events", + "description": "fetch data from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events_by_pk", + "description": "fetch data from the table: \"raw_events\" using primary key columns", + "args": [ + { + "name": "serial", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events", + "description": "columns and relationships of \"raw_events\"", + "fields": [ + { + "name": "block_fields", + "description": null, + "args": [ + { + "name": "path", + "description": "JSON select path", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_hash", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "contract_name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "params", + "description": null, + "args": [ + { + "name": "path", + "description": "JSON select path", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "src_address", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "transaction_fields", + "description": null, + "args": [ + { + "name": "path", + "description": "JSON select path", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "description": "Boolean expression to filter rows from the table \"raw_events\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "block_fields", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_hash", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_number", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "contract_name", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "bigint_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_name", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "log_index", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "params", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "serial", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "bigint_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "src_address", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "transaction_fields", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "description": "Ordering options when selecting data from \"raw_events\".", + "fields": null, + "inputFields": [ + { + "name": "block_fields", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_hash", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_number", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "contract_name", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_name", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "log_index", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "params", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "serial", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "src_address", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "transaction_fields", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "raw_events_select_column", + "description": "select columns of table \"raw_events\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "block_fields", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_hash", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_number", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "contract_name", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_name", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "params", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "src_address", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "transaction_fields", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "raw_events_stream_cursor_input", + "description": "Streaming cursor of the table \"raw_events\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "raw_events_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "block_fields", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_hash", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_number", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "contract_name", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_name", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "log_index", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "params", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "serial", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "src_address", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "transaction_fields", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "subscription_root", + "description": null, + "fields": [ + { + "name": "A", + "description": "fetch data from the table: \"A\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "A_by_pk", + "description": "fetch data from the table: \"A\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "A", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "A_stream", + "description": "fetch data from the table in a streaming manner: \"A\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B", + "description": "fetch data from the table: \"B\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "B_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "B", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B_by_pk", + "description": "fetch data from the table: \"B\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "B", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B_stream", + "description": "fetch data from the table in a streaming manner: \"B\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "B", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C", + "description": "fetch data from the table: \"C\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "C_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "C", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C_by_pk", + "description": "fetch data from the table: \"C\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "C", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C_stream", + "description": "fetch data from the table in a streaming manner: \"C\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "C", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass", + "description": "fetch data from the table: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass_by_pk", + "description": "fetch data from the table: \"CustomSelectionTestPass\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass_stream", + "description": "fetch data from the table in a streaming manner: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D", + "description": "fetch data from the table: \"D\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D_by_pk", + "description": "fetch data from the table: \"D\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "D", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D_stream", + "description": "fetch data from the table in a streaming manner: \"D\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes", + "description": "fetch data from the table: \"EntityWithAllTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithAllTypes\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal", + "description": "fetch data from the table: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal_by_pk", + "description": "fetch data from the table: \"EntityWithBigDecimal\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField_by_pk", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp", + "description": "fetch data from the table: \"EntityWithTimestamp\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp_by_pk", + "description": "fetch data from the table: \"EntityWithTimestamp\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithTimestamp\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar", + "description": "fetch data from the table: \"Gravatar\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Gravatar_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar_by_pk", + "description": "fetch data from the table: \"Gravatar\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar_stream", + "description": "fetch data from the table in a streaming manner: \"Gravatar\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection", + "description": "fetch data from the table: \"NftCollection\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "NftCollection_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection_by_pk", + "description": "fetch data from the table: \"NftCollection\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection_stream", + "description": "fetch data from the table in a streaming manner: \"NftCollection\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester_by_pk", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester_stream", + "description": "fetch data from the table in a streaming manner: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity", + "description": "fetch data from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity_by_pk", + "description": "fetch data from the table: \"SimpleEntity\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity_stream", + "description": "fetch data from the table in a streaming manner: \"SimpleEntity\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent", + "description": "fetch data from the table: \"SimulateTestEvent\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent_by_pk", + "description": "fetch data from the table: \"SimulateTestEvent\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent_stream", + "description": "fetch data from the table in a streaming manner: \"SimulateTestEvent\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token", + "description": "fetch data from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token_by_pk", + "description": "fetch data from the table: \"Token\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token_stream", + "description": "fetch data from the table in a streaming manner: \"Token\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User", + "description": "fetch data from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User_by_pk", + "description": "fetch data from the table: \"User\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User_stream", + "description": "fetch data from the table in a streaming manner: \"User\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "_meta", + "description": "fetch data from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "_meta_stream", + "description": "fetch data from the table in a streaming manner: \"_meta\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_metadata", + "description": "fetch data from the table: \"chain_metadata\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "chain_metadata", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_metadata_stream", + "description": "fetch data from the table in a streaming manner: \"chain_metadata\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "chain_metadata", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events", + "description": "fetch data from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events_by_pk", + "description": "fetch data from the table: \"raw_events\" using primary key columns", + "args": [ + { + "name": "serial", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events_stream", + "description": "fetch data from the table in a streaming manner: \"raw_events\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "timestamptz", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "description": "Boolean expression to compare columns of type \"timestamptz\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + } + ], + "directives": [ + { + "name": "include", + "description": "whether this query should be included", + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], + "args": [ + { + "name": "if", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "defaultValue": null + } + ] + }, + { + "name": "skip", + "description": "whether this query should be skipped", + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], + "args": [ + { + "name": "if", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "defaultValue": null + } + ] + }, + { + "name": "cached", + "description": "whether this query should be cached (Hasura Cloud only)", + "locations": [ + "QUERY" + ], + "args": [ + { + "name": "ttl", + "description": "measured in seconds", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": "60" + }, + { + "name": "refresh", + "description": "refresh the cache entry", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "defaultValue": "false" + } + ] + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-mixed-with-data.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-mixed-with-data.json new file mode 100644 index 0000000000..0b3926398c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-mixed-with-data.json @@ -0,0 +1,22 @@ +{ + "role": "public", + "request": { + "query": "{ __schema { queryType { name } } User(order_by: {id: asc}, limit: 1) { id __typename } }" + }, + "status": 200, + "body": { + "data": { + "__schema": { + "queryType": { + "name": "query_root" + } + }, + "User": [ + { + "id": "user \"quoted\" 🚀", + "__typename": "User" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-stream-cursor-types.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-stream-cursor-types.json new file mode 100644 index 0000000000..368cf4b6d7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-stream-cursor-types.json @@ -0,0 +1,85 @@ +{ + "role": "public", + "request": { + "query": "{ cursor: __type(name: \"User_stream_cursor_input\") { inputFields { name type { kind name ofType { kind name } } } } value: __type(name: \"User_stream_cursor_value_input\") { inputFields { name type { kind name } } } ordering: __type(name: \"cursor_ordering\") { enumValues { name description } } }" + }, + "status": 200, + "body": { + "data": { + "cursor": { + "inputFields": [ + { + "name": "initial_value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_value_input" + } + } + }, + { + "name": "ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + } + } + ] + }, + "value": { + "inputFields": [ + { + "name": "accountType", + "type": { + "kind": "SCALAR", + "name": "accounttype" + } + }, + { + "name": "address", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "gravatar_id", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "updatesCountOnUserForTesting", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ] + }, + "ordering": { + "enumValues": [ + { + "name": "ASC", + "description": "ascending ordering of the cursor" + }, + { + "name": "DESC", + "description": "descending ordering of the cursor" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-bool-exp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-bool-exp.json new file mode 100644 index 0000000000..a287bc4d14 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-bool-exp.json @@ -0,0 +1,111 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"User_bool_exp\") { kind name inputFields { name type { kind name ofType { kind name ofType { kind name } } } } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "inputFields": [ + { + "name": "_and", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp" + } + } + } + }, + { + "name": "_not", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + } + }, + { + "name": "_or", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp" + } + } + } + }, + { + "name": "accountType", + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + } + }, + { + "name": "address", + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + } + }, + { + "name": "gravatar", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + } + }, + { + "name": "gravatar_id", + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + } + }, + { + "name": "id", + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + } + }, + { + "name": "tokens", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + } + }, + { + "name": "updatesCountOnUserForTesting", + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-comparison-exp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-comparison-exp.json new file mode 100644 index 0000000000..27c1b5451f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-comparison-exp.json @@ -0,0 +1,95 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"numeric_comparison_exp\") { kind name inputFields { name type { kind name ofType { kind name } } } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "inputFields": [ + { + "name": "_eq", + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + { + "name": "_gt", + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + { + "name": "_gte", + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + { + "name": "_in", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null + } + } + }, + { + "name": "_is_null", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + { + "name": "_lt", + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + { + "name": "_lte", + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + { + "name": "_neq", + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + { + "name": "_nin", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null + } + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-entity.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-entity.json new file mode 100644 index 0000000000..45ebc9813b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-entity.json @@ -0,0 +1,97 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"User\") { kind name description fields { name type { kind name ofType { kind name ofType { kind name } } } } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "kind": "OBJECT", + "name": "User", + "description": "A user of the protocol, keyed by their wallet address.", + "fields": [ + { + "name": "accountType", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + } + }, + { + "name": "address", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + { + "name": "gravatar", + "type": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + } + }, + { + "name": "gravatar_id", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + { + "name": "tokens", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null + } + } + } + }, + { + "name": "updatesCountOnUserForTesting", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-missing.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-missing.json new file mode 100644 index 0000000000..dc41c60735 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-missing.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"DoesNotExist\") { kind name } }" + }, + "status": 200, + "body": { + "data": { + "__type": null + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-order-by-enum.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-order-by-enum.json new file mode 100644 index 0000000000..8eefee09bd --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-order-by-enum.json @@ -0,0 +1,41 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"order_by\") { kind name enumValues { name description } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "kind": "ENUM", + "name": "order_by", + "enumValues": [ + { + "name": "asc", + "description": "in ascending order, nulls last" + }, + { + "name": "asc_nulls_first", + "description": "in ascending order, nulls first" + }, + { + "name": "asc_nulls_last", + "description": "in ascending order, nulls last" + }, + { + "name": "desc", + "description": "in descending order, nulls first" + }, + { + "name": "desc_nulls_first", + "description": "in descending order, nulls first" + }, + { + "name": "desc_nulls_last", + "description": "in descending order, nulls last" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-pg-enum-scalar.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-pg-enum-scalar.json new file mode 100644 index 0000000000..61403090ad --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-pg-enum-scalar.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"accounttype\") { kind name description } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "kind": "SCALAR", + "name": "accounttype", + "description": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-select-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-select-column.json new file mode 100644 index 0000000000..f2ea016ce6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-type-select-column.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"Token_select_column\") { kind name enumValues { name description } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "kind": "ENUM", + "name": "Token_select_column", + "enumValues": [ + { + "name": "collection_id", + "description": "column name" + }, + { + "name": "id", + "description": "column name" + }, + { + "name": "owner_id", + "description": "column name" + }, + { + "name": "tokenId", + "description": "column name" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-typename-meta.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-typename-meta.json new file mode 100644 index 0000000000..888851c3fe --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-typename-meta.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ __schema { queryType { name } } }" + }, + "status": 200, + "body": { + "data": { + "__schema": { + "queryType": { + "name": "query_root" + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-typename-on-typed-queries.json b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-typename-on-typed-queries.json new file mode 100644 index 0000000000..d04f489d72 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/introspection-typename-on-typed-queries.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"User\") { __typename } __schema { __typename } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "__typename": "__Type" + }, + "__schema": { + "__typename": "__Schema" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/limit-basic.json b/packages/e2e-tests/fixtures/differential/snapshots/default/limit-basic.json new file mode 100644 index 0000000000..5216552706 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/limit-basic.json @@ -0,0 +1,22 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}, limit: 3) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/limit-larger-than-rows.json b/packages/e2e-tests/fixtures/differential/snapshots/default/limit-larger-than-rows.json new file mode 100644 index 0000000000..4c307df83c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/limit-larger-than-rows.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}, limit: 5000) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/limit-offset-combo.json b/packages/e2e-tests/fixtures/differential/snapshots/default/limit-offset-combo.json new file mode 100644 index 0000000000..253f7c0f9d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/limit-offset-combo.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}, limit: 2, offset: 2) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-2" + }, + { + "id": "simple-3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/limit-zero.json b/packages/e2e-tests/fixtures/differential/snapshots/default/limit-zero.json new file mode 100644 index 0000000000..a2dc0ec9d1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/limit-zero.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 0) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/offset-basic.json b/packages/e2e-tests/fixtures/differential/snapshots/default/offset-basic.json new file mode 100644 index 0000000000..1229f8cdac --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/offset-basic.json @@ -0,0 +1,34 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}, offset: 3) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/offset-beyond-rows.json b/packages/e2e-tests/fixtures/differential/snapshots/default/offset-beyond-rows.json new file mode 100644 index 0000000000..e67fa8402a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/offset-beyond-rows.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}, offset: 500) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/offset-without-order.json b/packages/e2e-tests/fixtures/differential/snapshots/default/offset-without-order.json new file mode 100644 index 0000000000..35181953bc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/offset-without-order.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(offset: 8) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-9" + }, + { + "id": "simple-10" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-extra-order-keys.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-extra-order-keys.json new file mode 100644 index 0000000000..a1eb046527 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-extra-order-keys.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ Token(distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}, {id: asc}]) { owner_id tokenId id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "owner_id": "user \"quoted\" 🚀", + "tokenId": "8", + "id": "tok-8" + }, + { + "owner_id": "user-1", + "tokenId": "7", + "id": "tok-7" + }, + { + "owner_id": "user-2", + "tokenId": "1000000000000000000000000000000", + "id": "tok-4" + }, + { + "owner_id": "user-3", + "tokenId": "-5", + "id": "tok-5" + }, + { + "owner_id": "user-4", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999", + "id": "tok-9" + }, + { + "owner_id": "user-missing", + "tokenId": "123456789", + "id": "tok-6" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-multi-prefix-swapped.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-multi-prefix-swapped.json new file mode 100644 index 0000000000..7de39d61ea --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-multi-prefix-swapped.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(distinct_on: [blockNumber, logIndex], order_by: [{logIndex: asc}, {blockNumber: asc}, {id: asc}]) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-1", + "blockNumber": 100, + "logIndex": 0 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + }, + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + }, + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + }, + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-no-order-by.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-no-order-by.json new file mode 100644 index 0000000000..c39bce821b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-no-order-by.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ Token(distinct_on: owner_id) { owner_id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "owner_id": "user \"quoted\" 🚀" + }, + { + "owner_id": "user-1" + }, + { + "owner_id": "user-2" + }, + { + "owner_id": "user-3" + }, + { + "owner_id": "user-4" + }, + { + "owner_id": "user-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-same-column-twice.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-same-column-twice.json new file mode 100644 index 0000000000..f51e5b2578 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-distinct-same-column-twice.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ Token(distinct_on: [owner_id, owner_id], order_by: [{owner_id: asc}, {id: asc}]) { owner_id id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "owner_id": "user \"quoted\" 🚀", + "id": "tok-8" + }, + { + "owner_id": "user-1", + "id": "tok-1" + }, + { + "owner_id": "user-2", + "id": "tok-3" + }, + { + "owner_id": "user-3", + "id": "tok-5" + }, + { + "owner_id": "user-4", + "id": "tok-10" + }, + { + "owner_id": "user-missing", + "id": "tok-6" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-distinct-not-first-in-order.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-distinct-not-first-in-order.json new file mode 100644 index 0000000000..81b91012d1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-distinct-not-first-in-order.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ Token(distinct_on: owner_id, order_by: [{tokenId: asc}, {owner_id: asc}]) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "\"distinct_on\" columns must match initial \"order_by\" columns", + "extensions": { + "path": "$.selectionSet.Token.args", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-distinct-unknown-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-distinct-unknown-column.json new file mode 100644 index 0000000000..72d2f136d0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-distinct-unknown-column.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ Token(distinct_on: bogus) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected one of the values ['id', 'collection_id', 'owner_id', 'tokenId'] for type 'Token_select_column', but found 'bogus'", + "extensions": { + "path": "$.selectionSet.Token.args.distinct_on[0]", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-order-array-rel-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-order-array-rel-column.json new file mode 100644 index 0000000000..52e4584f44 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-order-array-rel-column.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {tokens: {tokenId: asc}}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'tokens' not found in type: 'User_order_by'", + "extensions": { + "path": "$.selectionSet.User.args.order_by[0].tokens", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-order-duplicate-key-in-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-order-duplicate-key-in-object.json new file mode 100644 index 0000000000..d813ef65e3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-order-duplicate-key-in-object.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: {blockNumber: asc, blockNumber: desc}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "not a valid graphql query", + "extensions": { + "path": "$.query", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-order-unknown-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-order-unknown-column.json new file mode 100644 index 0000000000..755d854daf --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-error-order-unknown-column.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {bogus: asc}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'bogus' not found in type: 'User_order_by'", + "extensions": { + "path": "$.selectionSet.User.args.order_by[0].bogus", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-introspect-token-aggregate-order-by.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-introspect-token-aggregate-order-by.json new file mode 100644 index 0000000000..a30745427c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-introspect-token-aggregate-order-by.json @@ -0,0 +1,92 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"Token_aggregate_order_by\") { inputFields { name type { name kind } } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "inputFields": [ + { + "name": "avg", + "type": { + "name": "Token_avg_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "count", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "max", + "type": { + "name": "Token_max_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "min", + "type": { + "name": "Token_min_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "stddev", + "type": { + "name": "Token_stddev_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "stddev_pop", + "type": { + "name": "Token_stddev_pop_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "stddev_samp", + "type": { + "name": "Token_stddev_samp_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "sum", + "type": { + "name": "Token_sum_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "var_pop", + "type": { + "name": "Token_var_pop_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "var_samp", + "type": { + "name": "Token_var_samp_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "variance", + "type": { + "name": "Token_variance_order_by", + "kind": "INPUT_OBJECT" + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-introspect-user-order-by.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-introspect-user-order-by.json new file mode 100644 index 0000000000..64e57b4280 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-introspect-user-order-by.json @@ -0,0 +1,64 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"User_order_by\") { inputFields { name type { name kind } } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "inputFields": [ + { + "name": "accountType", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "address", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "gravatar", + "type": { + "name": "Gravatar_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "gravatar_id", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "id", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "tokens_aggregate", + "type": { + "name": "Token_aggregate_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "updatesCountOnUserForTesting", + "type": { + "name": "order_by", + "kind": "ENUM" + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-array-rel-aggregate-count-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-array-rel-aggregate-count-desc.json new file mode 100644 index 0000000000..0c25b3864f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-array-rel-aggregate-count-desc.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: [{tokens_aggregate: {count: desc}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-4" + }, + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-3" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-array-rel-aggregate-max.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-array-rel-aggregate-max.json new file mode 100644 index 0000000000..b42ded2dda --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-array-rel-aggregate-max.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: [{tokens_aggregate: {max: {tokenId: desc}}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-dangling" + }, + { + "id": "user-4" + }, + { + "id": "user-2" + }, + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-bigint-raw-events-asc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-bigint-raw-events-asc.json new file mode 100644 index 0000000000..4446cedc64 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-bigint-raw-events-asc.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(order_by: [{event_id: asc}, {serial: asc}]) { serial chain_id event_id } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "4", + "chain_id": 1337, + "event_id": "1" + }, + { + "serial": "5", + "chain_id": 1337, + "event_id": "2" + }, + { + "serial": "1", + "chain_id": 1, + "event_id": "4611686018427387904" + }, + { + "serial": "2", + "chain_id": 1, + "event_id": "4611686018427387905" + }, + { + "serial": "3", + "chain_id": 1, + "event_id": "4611686018427387906" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-bigint-raw-events-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-bigint-raw-events-desc.json new file mode 100644 index 0000000000..9fc1454f9b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-bigint-raw-events-desc.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(order_by: [{event_id: desc}, {serial: asc}]) { serial chain_id event_id } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "3", + "chain_id": 1, + "event_id": "4611686018427387906" + }, + { + "serial": "2", + "chain_id": 1, + "event_id": "4611686018427387905" + }, + { + "serial": "1", + "chain_id": 1, + "event_id": "4611686018427387904" + }, + { + "serial": "5", + "chain_id": 1337, + "event_id": "2" + }, + { + "serial": "4", + "chain_id": 1337, + "event_id": "1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-bool-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-bool-desc.json new file mode 100644 index 0000000000..7715fa6944 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-bool-desc.json @@ -0,0 +1,45 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(order_by: [{bool: desc}, {id: asc}]) { id bool } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-1", + "bool": true + }, + { + "id": "scalar-empty", + "bool": true + }, + { + "id": "scalar-extremes", + "bool": true + }, + { + "id": "scalar-neg-inf", + "bool": true + }, + { + "id": "scalar-unicode", + "bool": true + }, + { + "id": "scalar-nulls", + "bool": false + }, + { + "id": "scalar-quotes", + "bool": false + }, + { + "id": "scalar-special-float", + "bool": false + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-empty-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-empty-list.json new file mode 100644 index 0000000000..0f7429f6f7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-empty-list.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: []) { id value } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1", + "value": "v1" + }, + { + "id": "simple-2", + "value": "v2" + }, + { + "id": "simple-3", + "value": "v3" + }, + { + "id": "simple-4", + "value": "v4" + }, + { + "id": "simple-5", + "value": "v5" + }, + { + "id": "simple-6", + "value": "v6" + }, + { + "id": "simple-7", + "value": "v7" + }, + { + "id": "simple-8", + "value": "v8" + }, + { + "id": "simple-9", + "value": "v9" + }, + { + "id": "simple-10", + "value": "v10" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-empty-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-empty-object.json new file mode 100644 index 0000000000..33f3a4eae1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-empty-object.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + }, + { + "id": "simple-10" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-list-with-empty-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-list-with-empty-object.json new file mode 100644 index 0000000000..5f20cdcb77 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-list-with-empty-object.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: [{}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + }, + { + "id": "simple-10" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-null.json new file mode 100644 index 0000000000..c2319ecc96 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-null.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: null) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + }, + { + "id": "simple-10" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-variable-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-variable-null.json new file mode 100644 index 0000000000..69cea3430b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-by-variable-null.json @@ -0,0 +1,46 @@ +{ + "role": "public", + "request": { + "query": "query ($ord: [SimpleEntity_order_by!]) { SimpleEntity(order_by: $ord) { id } }", + "variables": { + "ord": null + } + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + }, + { + "id": "simple-10" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-bigint.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-bigint.json new file mode 100644 index 0000000000..1c0ab3a71f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-bigint.json @@ -0,0 +1,215 @@ +{ + "role": "public", + "request": { + "query": "{ d1: EntityWithAllNonArrayTypes(order_by: [{optBigInt: asc}, {id: asc}]) { id optBigInt } d2: EntityWithAllNonArrayTypes(order_by: [{optBigInt: desc}, {id: asc}]) { id optBigInt } d3: EntityWithAllNonArrayTypes(order_by: [{optBigInt: asc_nulls_first}, {id: asc}]) { id optBigInt } d4: EntityWithAllNonArrayTypes(order_by: [{optBigInt: asc_nulls_last}, {id: asc}]) { id optBigInt } d5: EntityWithAllNonArrayTypes(order_by: [{optBigInt: desc_nulls_first}, {id: asc}]) { id optBigInt } d6: EntityWithAllNonArrayTypes(order_by: [{optBigInt: desc_nulls_last}, {id: asc}]) { id optBigInt } }" + }, + "status": 200, + "body": { + "data": { + "d1": [ + { + "id": "scalar-extremes", + "optBigInt": "-9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "scalar-unicode", + "optBigInt": "-42" + }, + { + "id": "scalar-empty", + "optBigInt": "0" + }, + { + "id": "scalar-quotes", + "optBigInt": "8" + }, + { + "id": "scalar-1", + "optBigInt": "200" + }, + { + "id": "scalar-neg-inf", + "optBigInt": null + }, + { + "id": "scalar-nulls", + "optBigInt": null + }, + { + "id": "scalar-special-float", + "optBigInt": null + } + ], + "d2": [ + { + "id": "scalar-neg-inf", + "optBigInt": null + }, + { + "id": "scalar-nulls", + "optBigInt": null + }, + { + "id": "scalar-special-float", + "optBigInt": null + }, + { + "id": "scalar-1", + "optBigInt": "200" + }, + { + "id": "scalar-quotes", + "optBigInt": "8" + }, + { + "id": "scalar-empty", + "optBigInt": "0" + }, + { + "id": "scalar-unicode", + "optBigInt": "-42" + }, + { + "id": "scalar-extremes", + "optBigInt": "-9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ], + "d3": [ + { + "id": "scalar-neg-inf", + "optBigInt": null + }, + { + "id": "scalar-nulls", + "optBigInt": null + }, + { + "id": "scalar-special-float", + "optBigInt": null + }, + { + "id": "scalar-extremes", + "optBigInt": "-9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "scalar-unicode", + "optBigInt": "-42" + }, + { + "id": "scalar-empty", + "optBigInt": "0" + }, + { + "id": "scalar-quotes", + "optBigInt": "8" + }, + { + "id": "scalar-1", + "optBigInt": "200" + } + ], + "d4": [ + { + "id": "scalar-extremes", + "optBigInt": "-9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "scalar-unicode", + "optBigInt": "-42" + }, + { + "id": "scalar-empty", + "optBigInt": "0" + }, + { + "id": "scalar-quotes", + "optBigInt": "8" + }, + { + "id": "scalar-1", + "optBigInt": "200" + }, + { + "id": "scalar-neg-inf", + "optBigInt": null + }, + { + "id": "scalar-nulls", + "optBigInt": null + }, + { + "id": "scalar-special-float", + "optBigInt": null + } + ], + "d5": [ + { + "id": "scalar-neg-inf", + "optBigInt": null + }, + { + "id": "scalar-nulls", + "optBigInt": null + }, + { + "id": "scalar-special-float", + "optBigInt": null + }, + { + "id": "scalar-1", + "optBigInt": "200" + }, + { + "id": "scalar-quotes", + "optBigInt": "8" + }, + { + "id": "scalar-empty", + "optBigInt": "0" + }, + { + "id": "scalar-unicode", + "optBigInt": "-42" + }, + { + "id": "scalar-extremes", + "optBigInt": "-9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ], + "d6": [ + { + "id": "scalar-1", + "optBigInt": "200" + }, + { + "id": "scalar-quotes", + "optBigInt": "8" + }, + { + "id": "scalar-empty", + "optBigInt": "0" + }, + { + "id": "scalar-unicode", + "optBigInt": "-42" + }, + { + "id": "scalar-extremes", + "optBigInt": "-9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "scalar-neg-inf", + "optBigInt": null + }, + { + "id": "scalar-nulls", + "optBigInt": null + }, + { + "id": "scalar-special-float", + "optBigInt": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-enum.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-enum.json new file mode 100644 index 0000000000..8f3e288b0f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-enum.json @@ -0,0 +1,215 @@ +{ + "role": "public", + "request": { + "query": "{ d1: EntityWithAllNonArrayTypes(order_by: [{optEnumField: asc}, {id: asc}]) { id optEnumField } d2: EntityWithAllNonArrayTypes(order_by: [{optEnumField: desc}, {id: asc}]) { id optEnumField } d3: EntityWithAllNonArrayTypes(order_by: [{optEnumField: asc_nulls_first}, {id: asc}]) { id optEnumField } d4: EntityWithAllNonArrayTypes(order_by: [{optEnumField: asc_nulls_last}, {id: asc}]) { id optEnumField } d5: EntityWithAllNonArrayTypes(order_by: [{optEnumField: desc_nulls_first}, {id: asc}]) { id optEnumField } d6: EntityWithAllNonArrayTypes(order_by: [{optEnumField: desc_nulls_last}, {id: asc}]) { id optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "d1": [ + { + "id": "scalar-empty", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-extremes", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-1", + "optEnumField": "USER" + }, + { + "id": "scalar-quotes", + "optEnumField": "USER" + }, + { + "id": "scalar-unicode", + "optEnumField": "USER" + }, + { + "id": "scalar-neg-inf", + "optEnumField": null + }, + { + "id": "scalar-nulls", + "optEnumField": null + }, + { + "id": "scalar-special-float", + "optEnumField": null + } + ], + "d2": [ + { + "id": "scalar-neg-inf", + "optEnumField": null + }, + { + "id": "scalar-nulls", + "optEnumField": null + }, + { + "id": "scalar-special-float", + "optEnumField": null + }, + { + "id": "scalar-1", + "optEnumField": "USER" + }, + { + "id": "scalar-quotes", + "optEnumField": "USER" + }, + { + "id": "scalar-unicode", + "optEnumField": "USER" + }, + { + "id": "scalar-empty", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-extremes", + "optEnumField": "ADMIN" + } + ], + "d3": [ + { + "id": "scalar-neg-inf", + "optEnumField": null + }, + { + "id": "scalar-nulls", + "optEnumField": null + }, + { + "id": "scalar-special-float", + "optEnumField": null + }, + { + "id": "scalar-empty", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-extremes", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-1", + "optEnumField": "USER" + }, + { + "id": "scalar-quotes", + "optEnumField": "USER" + }, + { + "id": "scalar-unicode", + "optEnumField": "USER" + } + ], + "d4": [ + { + "id": "scalar-empty", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-extremes", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-1", + "optEnumField": "USER" + }, + { + "id": "scalar-quotes", + "optEnumField": "USER" + }, + { + "id": "scalar-unicode", + "optEnumField": "USER" + }, + { + "id": "scalar-neg-inf", + "optEnumField": null + }, + { + "id": "scalar-nulls", + "optEnumField": null + }, + { + "id": "scalar-special-float", + "optEnumField": null + } + ], + "d5": [ + { + "id": "scalar-neg-inf", + "optEnumField": null + }, + { + "id": "scalar-nulls", + "optEnumField": null + }, + { + "id": "scalar-special-float", + "optEnumField": null + }, + { + "id": "scalar-1", + "optEnumField": "USER" + }, + { + "id": "scalar-quotes", + "optEnumField": "USER" + }, + { + "id": "scalar-unicode", + "optEnumField": "USER" + }, + { + "id": "scalar-empty", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-extremes", + "optEnumField": "ADMIN" + } + ], + "d6": [ + { + "id": "scalar-1", + "optEnumField": "USER" + }, + { + "id": "scalar-quotes", + "optEnumField": "USER" + }, + { + "id": "scalar-unicode", + "optEnumField": "USER" + }, + { + "id": "scalar-empty", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-extremes", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-neg-inf", + "optEnumField": null + }, + { + "id": "scalar-nulls", + "optEnumField": null + }, + { + "id": "scalar-special-float", + "optEnumField": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-float.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-float.json new file mode 100644 index 0000000000..5124b046d3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-float.json @@ -0,0 +1,215 @@ +{ + "role": "public", + "request": { + "query": "{ d1: EntityWithAllNonArrayTypes(order_by: [{optFloat: asc}, {id: asc}]) { id optFloat } d2: EntityWithAllNonArrayTypes(order_by: [{optFloat: desc}, {id: asc}]) { id optFloat } d3: EntityWithAllNonArrayTypes(order_by: [{optFloat: asc_nulls_first}, {id: asc}]) { id optFloat } d4: EntityWithAllNonArrayTypes(order_by: [{optFloat: asc_nulls_last}, {id: asc}]) { id optFloat } d5: EntityWithAllNonArrayTypes(order_by: [{optFloat: desc_nulls_first}, {id: asc}]) { id optFloat } d6: EntityWithAllNonArrayTypes(order_by: [{optFloat: desc_nulls_last}, {id: asc}]) { id optFloat } }" + }, + "status": 200, + "body": { + "data": { + "d1": [ + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + }, + { + "id": "scalar-extremes", + "optFloat": "5e-324" + }, + { + "id": "scalar-quotes", + "optFloat": "0.2" + }, + { + "id": "scalar-1", + "optFloat": "2.5" + }, + { + "id": "scalar-unicode", + "optFloat": "2.718281828459045" + }, + { + "id": "scalar-special-float", + "optFloat": "NaN" + }, + { + "id": "scalar-nulls", + "optFloat": null + } + ], + "d2": [ + { + "id": "scalar-nulls", + "optFloat": null + }, + { + "id": "scalar-special-float", + "optFloat": "NaN" + }, + { + "id": "scalar-unicode", + "optFloat": "2.718281828459045" + }, + { + "id": "scalar-1", + "optFloat": "2.5" + }, + { + "id": "scalar-quotes", + "optFloat": "0.2" + }, + { + "id": "scalar-extremes", + "optFloat": "5e-324" + }, + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + } + ], + "d3": [ + { + "id": "scalar-nulls", + "optFloat": null + }, + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + }, + { + "id": "scalar-extremes", + "optFloat": "5e-324" + }, + { + "id": "scalar-quotes", + "optFloat": "0.2" + }, + { + "id": "scalar-1", + "optFloat": "2.5" + }, + { + "id": "scalar-unicode", + "optFloat": "2.718281828459045" + }, + { + "id": "scalar-special-float", + "optFloat": "NaN" + } + ], + "d4": [ + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + }, + { + "id": "scalar-extremes", + "optFloat": "5e-324" + }, + { + "id": "scalar-quotes", + "optFloat": "0.2" + }, + { + "id": "scalar-1", + "optFloat": "2.5" + }, + { + "id": "scalar-unicode", + "optFloat": "2.718281828459045" + }, + { + "id": "scalar-special-float", + "optFloat": "NaN" + }, + { + "id": "scalar-nulls", + "optFloat": null + } + ], + "d5": [ + { + "id": "scalar-nulls", + "optFloat": null + }, + { + "id": "scalar-special-float", + "optFloat": "NaN" + }, + { + "id": "scalar-unicode", + "optFloat": "2.718281828459045" + }, + { + "id": "scalar-1", + "optFloat": "2.5" + }, + { + "id": "scalar-quotes", + "optFloat": "0.2" + }, + { + "id": "scalar-extremes", + "optFloat": "5e-324" + }, + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + } + ], + "d6": [ + { + "id": "scalar-special-float", + "optFloat": "NaN" + }, + { + "id": "scalar-unicode", + "optFloat": "2.718281828459045" + }, + { + "id": "scalar-1", + "optFloat": "2.5" + }, + { + "id": "scalar-quotes", + "optFloat": "0.2" + }, + { + "id": "scalar-extremes", + "optFloat": "5e-324" + }, + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + }, + { + "id": "scalar-nulls", + "optFloat": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-int.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-int.json new file mode 100644 index 0000000000..ff755940f8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-int.json @@ -0,0 +1,215 @@ +{ + "role": "public", + "request": { + "query": "{ d1: EntityWithAllNonArrayTypes(order_by: [{optInt: asc}, {id: asc}]) { id optInt } d2: EntityWithAllNonArrayTypes(order_by: [{optInt: desc}, {id: asc}]) { id optInt } d3: EntityWithAllNonArrayTypes(order_by: [{optInt: asc_nulls_first}, {id: asc}]) { id optInt } d4: EntityWithAllNonArrayTypes(order_by: [{optInt: asc_nulls_last}, {id: asc}]) { id optInt } d5: EntityWithAllNonArrayTypes(order_by: [{optInt: desc_nulls_first}, {id: asc}]) { id optInt } d6: EntityWithAllNonArrayTypes(order_by: [{optInt: desc_nulls_last}, {id: asc}]) { id optInt } }" + }, + "status": 200, + "body": { + "data": { + "d1": [ + { + "id": "scalar-extremes", + "optInt": -2147483648 + }, + { + "id": "scalar-empty", + "optInt": 0 + }, + { + "id": "scalar-quotes", + "optInt": 3 + }, + { + "id": "scalar-unicode", + "optInt": 7 + }, + { + "id": "scalar-1", + "optInt": 10 + }, + { + "id": "scalar-neg-inf", + "optInt": null + }, + { + "id": "scalar-nulls", + "optInt": null + }, + { + "id": "scalar-special-float", + "optInt": null + } + ], + "d2": [ + { + "id": "scalar-neg-inf", + "optInt": null + }, + { + "id": "scalar-nulls", + "optInt": null + }, + { + "id": "scalar-special-float", + "optInt": null + }, + { + "id": "scalar-1", + "optInt": 10 + }, + { + "id": "scalar-unicode", + "optInt": 7 + }, + { + "id": "scalar-quotes", + "optInt": 3 + }, + { + "id": "scalar-empty", + "optInt": 0 + }, + { + "id": "scalar-extremes", + "optInt": -2147483648 + } + ], + "d3": [ + { + "id": "scalar-neg-inf", + "optInt": null + }, + { + "id": "scalar-nulls", + "optInt": null + }, + { + "id": "scalar-special-float", + "optInt": null + }, + { + "id": "scalar-extremes", + "optInt": -2147483648 + }, + { + "id": "scalar-empty", + "optInt": 0 + }, + { + "id": "scalar-quotes", + "optInt": 3 + }, + { + "id": "scalar-unicode", + "optInt": 7 + }, + { + "id": "scalar-1", + "optInt": 10 + } + ], + "d4": [ + { + "id": "scalar-extremes", + "optInt": -2147483648 + }, + { + "id": "scalar-empty", + "optInt": 0 + }, + { + "id": "scalar-quotes", + "optInt": 3 + }, + { + "id": "scalar-unicode", + "optInt": 7 + }, + { + "id": "scalar-1", + "optInt": 10 + }, + { + "id": "scalar-neg-inf", + "optInt": null + }, + { + "id": "scalar-nulls", + "optInt": null + }, + { + "id": "scalar-special-float", + "optInt": null + } + ], + "d5": [ + { + "id": "scalar-neg-inf", + "optInt": null + }, + { + "id": "scalar-nulls", + "optInt": null + }, + { + "id": "scalar-special-float", + "optInt": null + }, + { + "id": "scalar-1", + "optInt": 10 + }, + { + "id": "scalar-unicode", + "optInt": 7 + }, + { + "id": "scalar-quotes", + "optInt": 3 + }, + { + "id": "scalar-empty", + "optInt": 0 + }, + { + "id": "scalar-extremes", + "optInt": -2147483648 + } + ], + "d6": [ + { + "id": "scalar-1", + "optInt": 10 + }, + { + "id": "scalar-unicode", + "optInt": 7 + }, + { + "id": "scalar-quotes", + "optInt": 3 + }, + { + "id": "scalar-empty", + "optInt": 0 + }, + { + "id": "scalar-extremes", + "optInt": -2147483648 + }, + { + "id": "scalar-neg-inf", + "optInt": null + }, + { + "id": "scalar-nulls", + "optInt": null + }, + { + "id": "scalar-special-float", + "optInt": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-text.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-text.json new file mode 100644 index 0000000000..8f6323d436 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-text.json @@ -0,0 +1,167 @@ +{ + "role": "public", + "request": { + "query": "{ d1: User(order_by: [{gravatar_id: asc}, {id: asc}]) { id gravatar_id } d2: User(order_by: [{gravatar_id: desc}, {id: asc}]) { id gravatar_id } d3: User(order_by: [{gravatar_id: asc_nulls_first}, {id: asc}]) { id gravatar_id } d4: User(order_by: [{gravatar_id: asc_nulls_last}, {id: asc}]) { id gravatar_id } d5: User(order_by: [{gravatar_id: desc_nulls_first}, {id: asc}]) { id gravatar_id } d6: User(order_by: [{gravatar_id: desc_nulls_last}, {id: asc}]) { id gravatar_id } }" + }, + "status": 200, + "body": { + "data": { + "d1": [ + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + }, + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + } + ], + "d2": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + } + ], + "d3": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + } + ], + "d4": [ + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + }, + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + } + ], + "d5": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + } + ], + "d6": [ + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-timestamp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-timestamp.json new file mode 100644 index 0000000000..37fbeaa2f8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-directions-opt-timestamp.json @@ -0,0 +1,215 @@ +{ + "role": "public", + "request": { + "query": "{ d1: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: asc}, {id: asc}]) { id optTimestamp } d2: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: desc}, {id: asc}]) { id optTimestamp } d3: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: asc_nulls_first}, {id: asc}]) { id optTimestamp } d4: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: asc_nulls_last}, {id: asc}]) { id optTimestamp } d5: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: desc_nulls_first}, {id: asc}]) { id optTimestamp } d6: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: desc_nulls_last}, {id: asc}]) { id optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "d1": [ + { + "id": "scalar-extremes", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + }, + { + "id": "scalar-1", + "optTimestamp": "2024-01-15T12:34:56.789123+00:00" + }, + { + "id": "scalar-quotes", + "optTimestamp": "2024-03-10T10:00:00+00:00" + }, + { + "id": "scalar-empty", + "optTimestamp": "2024-07-04T00:00:00.12+00:00" + }, + { + "id": "scalar-unicode", + "optTimestamp": "2024-12-26T02:30:00+00:00" + }, + { + "id": "scalar-neg-inf", + "optTimestamp": null + }, + { + "id": "scalar-nulls", + "optTimestamp": null + }, + { + "id": "scalar-special-float", + "optTimestamp": null + } + ], + "d2": [ + { + "id": "scalar-neg-inf", + "optTimestamp": null + }, + { + "id": "scalar-nulls", + "optTimestamp": null + }, + { + "id": "scalar-special-float", + "optTimestamp": null + }, + { + "id": "scalar-unicode", + "optTimestamp": "2024-12-26T02:30:00+00:00" + }, + { + "id": "scalar-empty", + "optTimestamp": "2024-07-04T00:00:00.12+00:00" + }, + { + "id": "scalar-quotes", + "optTimestamp": "2024-03-10T10:00:00+00:00" + }, + { + "id": "scalar-1", + "optTimestamp": "2024-01-15T12:34:56.789123+00:00" + }, + { + "id": "scalar-extremes", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + } + ], + "d3": [ + { + "id": "scalar-neg-inf", + "optTimestamp": null + }, + { + "id": "scalar-nulls", + "optTimestamp": null + }, + { + "id": "scalar-special-float", + "optTimestamp": null + }, + { + "id": "scalar-extremes", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + }, + { + "id": "scalar-1", + "optTimestamp": "2024-01-15T12:34:56.789123+00:00" + }, + { + "id": "scalar-quotes", + "optTimestamp": "2024-03-10T10:00:00+00:00" + }, + { + "id": "scalar-empty", + "optTimestamp": "2024-07-04T00:00:00.12+00:00" + }, + { + "id": "scalar-unicode", + "optTimestamp": "2024-12-26T02:30:00+00:00" + } + ], + "d4": [ + { + "id": "scalar-extremes", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + }, + { + "id": "scalar-1", + "optTimestamp": "2024-01-15T12:34:56.789123+00:00" + }, + { + "id": "scalar-quotes", + "optTimestamp": "2024-03-10T10:00:00+00:00" + }, + { + "id": "scalar-empty", + "optTimestamp": "2024-07-04T00:00:00.12+00:00" + }, + { + "id": "scalar-unicode", + "optTimestamp": "2024-12-26T02:30:00+00:00" + }, + { + "id": "scalar-neg-inf", + "optTimestamp": null + }, + { + "id": "scalar-nulls", + "optTimestamp": null + }, + { + "id": "scalar-special-float", + "optTimestamp": null + } + ], + "d5": [ + { + "id": "scalar-neg-inf", + "optTimestamp": null + }, + { + "id": "scalar-nulls", + "optTimestamp": null + }, + { + "id": "scalar-special-float", + "optTimestamp": null + }, + { + "id": "scalar-unicode", + "optTimestamp": "2024-12-26T02:30:00+00:00" + }, + { + "id": "scalar-empty", + "optTimestamp": "2024-07-04T00:00:00.12+00:00" + }, + { + "id": "scalar-quotes", + "optTimestamp": "2024-03-10T10:00:00+00:00" + }, + { + "id": "scalar-1", + "optTimestamp": "2024-01-15T12:34:56.789123+00:00" + }, + { + "id": "scalar-extremes", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + } + ], + "d6": [ + { + "id": "scalar-unicode", + "optTimestamp": "2024-12-26T02:30:00+00:00" + }, + { + "id": "scalar-empty", + "optTimestamp": "2024-07-04T00:00:00.12+00:00" + }, + { + "id": "scalar-quotes", + "optTimestamp": "2024-03-10T10:00:00+00:00" + }, + { + "id": "scalar-1", + "optTimestamp": "2024-01-15T12:34:56.789123+00:00" + }, + { + "id": "scalar-extremes", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + }, + { + "id": "scalar-neg-inf", + "optTimestamp": null + }, + { + "id": "scalar-nulls", + "optTimestamp": null + }, + { + "id": "scalar-special-float", + "optTimestamp": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-enum-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-enum-desc.json new file mode 100644 index 0000000000..266ea7b6ac --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-enum-desc.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(order_by: [{size: desc}, {id: asc}]) { id size } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-3", + "size": "LARGE" + }, + { + "id": "grav-2", + "size": "MEDIUM" + }, + { + "id": "grav-1", + "size": "SMALL" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-float-special-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-float-special-desc.json new file mode 100644 index 0000000000..3d34210a8b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-float-special-desc.json @@ -0,0 +1,45 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(order_by: [{float_: desc}, {id: asc}]) { id float_ } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-special-float", + "float_": "Infinity" + }, + { + "id": "scalar-extremes", + "float_": "1.7976931348623157e+308" + }, + { + "id": "scalar-1", + "float_": "1.5" + }, + { + "id": "scalar-quotes", + "float_": "0.1" + }, + { + "id": "scalar-nulls", + "float_": "0" + }, + { + "id": "scalar-empty", + "float_": "-0.5" + }, + { + "id": "scalar-unicode", + "float_": "-3.14159" + }, + { + "id": "scalar-neg-inf", + "float_": "-Infinity" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-int-asc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-int-asc.json new file mode 100644 index 0000000000..2b91606e53 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-int-asc.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: [{updatesCountOnUserForTesting: asc}, {id: asc}]) { id updatesCountOnUserForTesting } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-4", + "updatesCountOnUserForTesting": -2147483648 + }, + { + "id": "user-1", + "updatesCountOnUserForTesting": 0 + }, + { + "id": "user \"quoted\" 🚀", + "updatesCountOnUserForTesting": 5 + }, + { + "id": "user-dangling", + "updatesCountOnUserForTesting": 7 + }, + { + "id": "user-2", + "updatesCountOnUserForTesting": 42 + }, + { + "id": "user-3", + "updatesCountOnUserForTesting": 2147483647 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-int-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-int-desc.json new file mode 100644 index 0000000000..f08d01fc48 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-int-desc.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: [{updatesCountOnUserForTesting: desc}, {id: asc}]) { id updatesCountOnUserForTesting } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-3", + "updatesCountOnUserForTesting": 2147483647 + }, + { + "id": "user-2", + "updatesCountOnUserForTesting": 42 + }, + { + "id": "user-dangling", + "updatesCountOnUserForTesting": 7 + }, + { + "id": "user \"quoted\" 🚀", + "updatesCountOnUserForTesting": 5 + }, + { + "id": "user-1", + "updatesCountOnUserForTesting": 0 + }, + { + "id": "user-4", + "updatesCountOnUserForTesting": -2147483648 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-jsonb-asc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-jsonb-asc.json new file mode 100644 index 0000000000..aec0aeeb9a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-jsonb-asc.json @@ -0,0 +1,69 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(order_by: [{json: asc}, {id: asc}]) { id json } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-json-null", + "json": null + }, + { + "id": "all-json-string", + "json": "just a string" + }, + { + "id": "all-json-number", + "json": 1.2345678901234568e+29 + }, + { + "id": "all-json-bool", + "json": false + }, + { + "id": "all-array-edge", + "json": [ + 1, + "two", + null, + true, + { + "k": "v" + }, + [ + 2.5 + ] + ] + }, + { + "id": "all-empty-arrays", + "json": {} + }, + { + "id": "all-json-unicode", + "json": { + "esc": "a\"b\\c\nd", + "num": 1e+100, + "héllo": "wörld 🚀" + } + }, + { + "id": "all-1", + "json": { + "n": 1, + "kind": "object", + "nested": { + "a": [ + 1, + 2 + ] + } + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-jsonb-desc-raw-events.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-jsonb-desc-raw-events.json new file mode 100644 index 0000000000..04e01385ac --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-jsonb-desc-raw-events.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(order_by: [{params: desc}, {serial: asc}]) { serial params } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "2", + "params": { + "to": "0x2", + "from": "0x1", + "value": "9999999999999999999999999999" + } + }, + { + "serial": "1", + "params": { + "to": "0x1", + "from": "0x0", + "value": "100" + } + }, + { + "serial": "3", + "params": { + "id": "1", + "nested": { + "deep": [ + 1, + null, + "x" + ] + }, + "displayName": "unicode 🚀" + } + }, + { + "serial": "5", + "params": { + "addr": "0x5555555555555555555555555555555555555555" + } + }, + { + "serial": "4", + "params": {} + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-mixed-list-with-multikey-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-mixed-list-with-multikey-object.json new file mode 100644 index 0000000000..3593858c14 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-mixed-list-with-multikey-object.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: [{blockNumber: desc, logIndex: desc}, {id: asc}]) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + }, + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + }, + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + }, + { + "id": "sim-1", + "blockNumber": 100, + "logIndex": 0 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-multi-conflicting-flipped.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-multi-conflicting-flipped.json new file mode 100644 index 0000000000..1cda2fd14b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-multi-conflicting-flipped.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: [{blockNumber: desc}, {logIndex: asc}, {id: asc}]) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + }, + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + }, + { + "id": "sim-1", + "blockNumber": 100, + "logIndex": 0 + }, + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-multi-conflicting.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-multi-conflicting.json new file mode 100644 index 0000000000..d0dccbfb58 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-multi-conflicting.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: [{blockNumber: asc}, {logIndex: desc}, {id: asc}]) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + }, + { + "id": "sim-1", + "blockNumber": 100, + "logIndex": 0 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + }, + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + }, + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-multi-list-respects-order.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-multi-list-respects-order.json new file mode 100644 index 0000000000..2e733108ad --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-multi-list-respects-order.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: [{logIndex: desc}, {blockNumber: asc}, {id: asc}]) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + }, + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + }, + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + }, + { + "id": "sim-1", + "blockNumber": 100, + "logIndex": 0 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-numeric-bigdecimal-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-numeric-bigdecimal-desc.json new file mode 100644 index 0000000000..ae5e13f22f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-numeric-bigdecimal-desc.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithBigDecimal(order_by: [{bigDecimal: desc}, {id: asc}]) { id bigDecimal } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithBigDecimal": [ + { + "id": "bd-4", + "bigDecimal": "123456789.123456789" + }, + { + "id": "bd-2", + "bigDecimal": "1.10" + }, + { + "id": "bd-5", + "bigDecimal": "0.000000000000000001" + }, + { + "id": "bd-1", + "bigDecimal": "0" + }, + { + "id": "bd-3", + "bigDecimal": "-1.10" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-numeric-bigint-asc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-numeric-bigint-asc.json new file mode 100644 index 0000000000..db9a5877f9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-numeric-bigint-asc.json @@ -0,0 +1,45 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(order_by: [{bigInt: asc}, {id: asc}]) { id bigInt } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-neg-inf", + "bigInt": "-1" + }, + { + "id": "scalar-nulls", + "bigInt": "0" + }, + { + "id": "scalar-special-float", + "bigInt": "1" + }, + { + "id": "scalar-quotes", + "bigInt": "7" + }, + { + "id": "scalar-empty", + "bigInt": "10" + }, + { + "id": "scalar-unicode", + "bigInt": "42" + }, + { + "id": "scalar-1", + "bigInt": "100" + }, + { + "id": "scalar-extremes", + "bigInt": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-keys-blocknumber-first.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-keys-blocknumber-first.json new file mode 100644 index 0000000000..e7282d23ad --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-keys-blocknumber-first.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: {blockNumber: asc, logIndex: desc, id: asc}) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-1", + "blockNumber": 100, + "logIndex": 0 + }, + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + }, + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + }, + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-keys-logindex-first.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-keys-logindex-first.json new file mode 100644 index 0000000000..5fd812008a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-keys-logindex-first.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: {logIndex: desc, blockNumber: asc, id: asc}) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-1", + "blockNumber": 100, + "logIndex": 0 + }, + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + }, + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + }, + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-rel-nested-aggregate.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-rel-nested-aggregate.json new file mode 100644 index 0000000000..a777c9b9a2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-rel-nested-aggregate.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: [{collection: {tokens_aggregate: {count: asc}}}, {id: asc}]) { id collection_id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-1", + "collection_id": "coll-1" + }, + { + "id": "tok-10", + "collection_id": "coll-1" + }, + { + "id": "tok-2", + "collection_id": "coll-1" + }, + { + "id": "tok-3", + "collection_id": "coll-1" + }, + { + "id": "tok-4", + "collection_id": "coll-2" + }, + { + "id": "tok-5", + "collection_id": "coll-2" + }, + { + "id": "tok-6", + "collection_id": "coll-2" + }, + { + "id": "tok-8", + "collection_id": "coll-2" + }, + { + "id": "tok-9", + "collection_id": "coll-2" + }, + { + "id": "tok-7", + "collection_id": "coll-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-rel-owner-id.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-rel-owner-id.json new file mode 100644 index 0000000000..14375738d3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-rel-owner-id.json @@ -0,0 +1,71 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: [{owner: {id: asc}}, {id: asc}]) { id owner { id } } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-8", + "owner": { + "id": "user \"quoted\" 🚀" + } + }, + { + "id": "tok-1", + "owner": { + "id": "user-1" + } + }, + { + "id": "tok-2", + "owner": { + "id": "user-1" + } + }, + { + "id": "tok-7", + "owner": { + "id": "user-1" + } + }, + { + "id": "tok-3", + "owner": { + "id": "user-2" + } + }, + { + "id": "tok-4", + "owner": { + "id": "user-2" + } + }, + { + "id": "tok-5", + "owner": { + "id": "user-3" + } + }, + { + "id": "tok-10", + "owner": { + "id": "user-4" + } + }, + { + "id": "tok-9", + "owner": { + "id": "user-4" + } + }, + { + "id": "tok-6", + "owner": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-rel-two-levels.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-rel-two-levels.json new file mode 100644 index 0000000000..61cc262adf --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-object-rel-two-levels.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: [{owner: {gravatar: {displayName: asc}}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-1" + }, + { + "id": "tok-2" + }, + { + "id": "tok-7" + }, + { + "id": "tok-3" + }, + { + "id": "tok-4" + }, + { + "id": "tok-10" + }, + { + "id": "tok-5" + }, + { + "id": "tok-6" + }, + { + "id": "tok-8" + }, + { + "id": "tok-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-optfloat-nan-asc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-optfloat-nan-asc.json new file mode 100644 index 0000000000..18cfbb3a03 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-optfloat-nan-asc.json @@ -0,0 +1,45 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(order_by: [{optFloat: asc}, {id: asc}]) { id optFloat } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + }, + { + "id": "scalar-extremes", + "optFloat": "5e-324" + }, + { + "id": "scalar-quotes", + "optFloat": "0.2" + }, + { + "id": "scalar-1", + "optFloat": "2.5" + }, + { + "id": "scalar-unicode", + "optFloat": "2.718281828459045" + }, + { + "id": "scalar-special-float", + "optFloat": "NaN" + }, + { + "id": "scalar-nulls", + "optFloat": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-optfloat-nan-desc-nulls-last.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-optfloat-nan-desc-nulls-last.json new file mode 100644 index 0000000000..f77db4b241 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-optfloat-nan-desc-nulls-last.json @@ -0,0 +1,45 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(order_by: [{optFloat: desc_nulls_last}, {id: asc}]) { id optFloat } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-special-float", + "optFloat": "NaN" + }, + { + "id": "scalar-unicode", + "optFloat": "2.718281828459045" + }, + { + "id": "scalar-1", + "optFloat": "2.5" + }, + { + "id": "scalar-quotes", + "optFloat": "0.2" + }, + { + "id": "scalar-extremes", + "optFloat": "5e-324" + }, + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + }, + { + "id": "scalar-nulls", + "optFloat": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-same-column-twice-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-same-column-twice-list.json new file mode 100644 index 0000000000..b82e7c869b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-same-column-twice-list.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: [{blockNumber: asc}, {blockNumber: desc}, {id: asc}]) { id blockNumber } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-1", + "blockNumber": 100 + }, + { + "id": "sim-2", + "blockNumber": 100 + }, + { + "id": "sim-3", + "blockNumber": 101 + }, + { + "id": "sim-4", + "blockNumber": 102 + }, + { + "id": "sim-5", + "blockNumber": 103 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-text-asc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-text-asc.json new file mode 100644 index 0000000000..57aa16a57a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-text-asc.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: [{value: asc}, {id: asc}]) { id value } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1", + "value": "v1" + }, + { + "id": "simple-10", + "value": "v10" + }, + { + "id": "simple-2", + "value": "v2" + }, + { + "id": "simple-3", + "value": "v3" + }, + { + "id": "simple-4", + "value": "v4" + }, + { + "id": "simple-5", + "value": "v5" + }, + { + "id": "simple-6", + "value": "v6" + }, + { + "id": "simple-7", + "value": "v7" + }, + { + "id": "simple-8", + "value": "v8" + }, + { + "id": "simple-9", + "value": "v9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-timestamp-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-timestamp-desc.json new file mode 100644 index 0000000000..52f8aca78a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/om-order-timestamp-desc.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp(order_by: [{timestamp: desc}, {id: asc}]) { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp": [ + { + "id": "ts-future", + "timestamp": "9999-12-31T23:59:59.999999+00:00" + }, + { + "id": "ts-zoned", + "timestamp": "2024-06-15T02:30:00+00:00" + }, + { + "id": "ts-micro", + "timestamp": "2024-01-15T12:34:56.123456+00:00" + }, + { + "id": "ts-milli", + "timestamp": "2024-01-15T12:34:56.123+00:00" + }, + { + "id": "ts-epoch", + "timestamp": "1970-01-01T00:00:00+00:00" + }, + { + "id": "ts-pre-epoch", + "timestamp": "1969-07-20T20:17:40+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-asc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-asc.json new file mode 100644 index 0000000000..d3b7d90b4a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-asc.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: {tokenId: asc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-5", + "tokenId": "-5" + }, + { + "id": "tok-1", + "tokenId": "0" + }, + { + "id": "tok-2", + "tokenId": "1" + }, + { + "id": "tok-3", + "tokenId": "2" + }, + { + "id": "tok-7", + "tokenId": "7" + }, + { + "id": "tok-8", + "tokenId": "8" + }, + { + "id": "tok-10", + "tokenId": "10" + }, + { + "id": "tok-6", + "tokenId": "123456789" + }, + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-bool.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-bool.json new file mode 100644 index 0000000000..ea6fe24a3d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-bool.json @@ -0,0 +1,45 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(order_by: [{bool: asc}, {id: asc}]) { id bool } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-nulls", + "bool": false + }, + { + "id": "scalar-quotes", + "bool": false + }, + { + "id": "scalar-special-float", + "bool": false + }, + { + "id": "scalar-1", + "bool": true + }, + { + "id": "scalar-empty", + "bool": true + }, + { + "id": "scalar-extremes", + "bool": true + }, + { + "id": "scalar-neg-inf", + "bool": true + }, + { + "id": "scalar-unicode", + "bool": true + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-enum-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-enum-column.json new file mode 100644 index 0000000000..4b5bbce97b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-enum-column.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(order_by: [{size: asc}, {id: asc}]) { id size } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-1", + "size": "SMALL" + }, + { + "id": "grav-2", + "size": "MEDIUM" + }, + { + "id": "grav-3", + "size": "LARGE" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-float-with-special.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-float-with-special.json new file mode 100644 index 0000000000..4b126af11f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-float-with-special.json @@ -0,0 +1,45 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(order_by: [{float_: asc}, {id: asc}]) { id float_ } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-neg-inf", + "float_": "-Infinity" + }, + { + "id": "scalar-unicode", + "float_": "-3.14159" + }, + { + "id": "scalar-empty", + "float_": "-0.5" + }, + { + "id": "scalar-nulls", + "float_": "0" + }, + { + "id": "scalar-quotes", + "float_": "0.1" + }, + { + "id": "scalar-1", + "float_": "1.5" + }, + { + "id": "scalar-extremes", + "float_": "1.7976931348623157e+308" + }, + { + "id": "scalar-special-float", + "float_": "Infinity" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-numeric.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-numeric.json new file mode 100644 index 0000000000..23a18a20cf --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-numeric.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: [{tokenId: desc}, {id: asc}]) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-6", + "tokenId": "123456789" + }, + { + "id": "tok-10", + "tokenId": "10" + }, + { + "id": "tok-8", + "tokenId": "8" + }, + { + "id": "tok-7", + "tokenId": "7" + }, + { + "id": "tok-3", + "tokenId": "2" + }, + { + "id": "tok-2", + "tokenId": "1" + }, + { + "id": "tok-1", + "tokenId": "0" + }, + { + "id": "tok-5", + "tokenId": "-5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-object-relationship-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-object-relationship-column.json new file mode 100644 index 0000000000..64668651c6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-object-relationship-column.json @@ -0,0 +1,29 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(order_by: [{owner: {updatesCountOnUserForTesting: desc}}, {id: asc}]) { id owner { updatesCountOnUserForTesting } } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-3", + "owner": null + }, + { + "id": "grav-2", + "owner": { + "updatesCountOnUserForTesting": 42 + } + }, + { + "id": "grav-1", + "owner": { + "updatesCountOnUserForTesting": 0 + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-relationship-nested.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-relationship-nested.json new file mode 100644 index 0000000000..b313798b53 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-relationship-nested.json @@ -0,0 +1,71 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: [{collection: {name: asc}}, {id: asc}]) { id collection { name } } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-1", + "collection": { + "name": "Alpha Apes" + } + }, + { + "id": "tok-10", + "collection": { + "name": "Alpha Apes" + } + }, + { + "id": "tok-2", + "collection": { + "name": "Alpha Apes" + } + }, + { + "id": "tok-3", + "collection": { + "name": "Alpha Apes" + } + }, + { + "id": "tok-4", + "collection": { + "name": "Béta Bots 🤖" + } + }, + { + "id": "tok-5", + "collection": { + "name": "Béta Bots 🤖" + } + }, + { + "id": "tok-6", + "collection": { + "name": "Béta Bots 🤖" + } + }, + { + "id": "tok-8", + "collection": { + "name": "Béta Bots 🤖" + } + }, + { + "id": "tok-9", + "collection": { + "name": "Béta Bots 🤖" + } + }, + { + "id": "tok-7", + "collection": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-timestamp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-timestamp.json new file mode 100644 index 0000000000..0006cd0785 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-by-timestamp.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp(order_by: [{timestamp: asc}, {id: asc}]) { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp": [ + { + "id": "ts-pre-epoch", + "timestamp": "1969-07-20T20:17:40+00:00" + }, + { + "id": "ts-epoch", + "timestamp": "1970-01-01T00:00:00+00:00" + }, + { + "id": "ts-milli", + "timestamp": "2024-01-15T12:34:56.123+00:00" + }, + { + "id": "ts-micro", + "timestamp": "2024-01-15T12:34:56.123456+00:00" + }, + { + "id": "ts-zoned", + "timestamp": "2024-06-15T02:30:00+00:00" + }, + { + "id": "ts-future", + "timestamp": "9999-12-31T23:59:59.999999+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-default-nulls-asc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-default-nulls-asc.json new file mode 100644 index 0000000000..38deb18665 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-default-nulls-asc.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {gravatar_id: asc, id: asc}) { id gravatar_id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-default-nulls-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-default-nulls-desc.json new file mode 100644 index 0000000000..ee9667cf81 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-default-nulls-desc.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {gravatar_id: desc, id: asc}) { id gravatar_id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-desc-nulls-first.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-desc-nulls-first.json new file mode 100644 index 0000000000..bf4fbb7a90 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-desc-nulls-first.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {gravatar_id: desc_nulls_first, id: asc}) { id gravatar_id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-desc-nulls-last.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-desc-nulls-last.json new file mode 100644 index 0000000000..41f3c2afe7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-desc-nulls-last.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {gravatar_id: desc_nulls_last, id: asc}) { id gravatar_id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-desc.json new file mode 100644 index 0000000000..0e6e7bf2c8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-desc.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: {tokenId: desc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-6", + "tokenId": "123456789" + }, + { + "id": "tok-10", + "tokenId": "10" + }, + { + "id": "tok-8", + "tokenId": "8" + }, + { + "id": "tok-7", + "tokenId": "7" + }, + { + "id": "tok-3", + "tokenId": "2" + }, + { + "id": "tok-2", + "tokenId": "1" + }, + { + "id": "tok-1", + "tokenId": "0" + }, + { + "id": "tok-5", + "tokenId": "-5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-multi-key-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-multi-key-list.json new file mode 100644 index 0000000000..b007603379 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-multi-key-list.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: [{blockNumber: desc}, {logIndex: asc}]) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + }, + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + }, + { + "id": "sim-1", + "blockNumber": 100, + "logIndex": 0 + }, + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-multi-key-single-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-multi-key-single-object.json new file mode 100644 index 0000000000..e31a62052f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-multi-key-single-object.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ SimulateTestEvent(order_by: {blockNumber: desc, logIndex: desc}) { id blockNumber logIndex } }" + }, + "status": 200, + "body": { + "data": { + "SimulateTestEvent": [ + { + "id": "sim-5", + "blockNumber": 103, + "logIndex": 2 + }, + { + "id": "sim-4", + "blockNumber": 102, + "logIndex": 5 + }, + { + "id": "sim-3", + "blockNumber": 101, + "logIndex": 0 + }, + { + "id": "sim-2", + "blockNumber": 100, + "logIndex": 1 + }, + { + "id": "sim-1", + "blockNumber": 100, + "logIndex": 0 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-nulls-first.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-nulls-first.json new file mode 100644 index 0000000000..7d519ed4e7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-nulls-first.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {gravatar_id: asc_nulls_first, id: asc}) { id gravatar_id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/order-nulls-last.json b/packages/e2e-tests/fixtures/differential/snapshots/default/order-nulls-last.json new file mode 100644 index 0000000000..31ee7754b4 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/order-nulls-last.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {gravatar_id: asc_nulls_last, id: asc}) { id gravatar_id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-abcd-chain.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-abcd-chain.json new file mode 100644 index 0000000000..84c128f9b2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-abcd-chain.json @@ -0,0 +1,50 @@ +{ + "role": "public", + "request": { + "query": "{ B(order_by: {id: asc}) { id c { id a { id b { id } } } a(order_by: {id: asc}) { id optionalStringToTestLinkedEntities } } }" + }, + "status": 200, + "body": { + "data": { + "B": [ + { + "id": "b-1", + "c": { + "id": "c-1", + "a": { + "id": "a-1", + "b": { + "id": "b-1" + } + } + }, + "a": [ + { + "id": "a-1", + "optionalStringToTestLinkedEntities": "linked" + }, + { + "id": "a-2", + "optionalStringToTestLinkedEntities": null + } + ] + }, + { + "id": "b-2", + "c": null, + "a": [ + { + "id": "a-3", + "optionalStringToTestLinkedEntities": "" + } + ] + }, + { + "id": "b-3", + "c": null, + "a": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-aliases-multiple-same-relationship.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-aliases-multiple-same-relationship.json new file mode 100644 index 0000000000..e3c9ab9ff3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-aliases-multiple-same-relationship.json @@ -0,0 +1,29 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {id: {_eq: \"user-1\"}}) { id low: tokens(where: {tokenId: {_lt: 1}}, order_by: {id: asc}) { id } high: tokens(where: {tokenId: {_gte: 1}}, order_by: {id: asc}) { id } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1", + "low": [ + { + "id": "tok-1" + } + ], + "high": [ + { + "id": "tok-2" + }, + { + "id": "tok-7" + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-basic.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-basic.json new file mode 100644 index 0000000000..16f1977d42 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-basic.json @@ -0,0 +1,78 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}) { id tokens(order_by: {id: asc}) { id tokenId } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "tokens": [ + { + "id": "tok-8", + "tokenId": "8" + } + ] + }, + { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "tokenId": "0" + }, + { + "id": "tok-2", + "tokenId": "1" + }, + { + "id": "tok-7", + "tokenId": "7" + } + ] + }, + { + "id": "user-2", + "tokens": [ + { + "id": "tok-3", + "tokenId": "2" + }, + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + } + ] + }, + { + "id": "user-3", + "tokens": [ + { + "id": "tok-5", + "tokenId": "-5" + } + ] + }, + { + "id": "user-4", + "tokens": [ + { + "id": "tok-10", + "tokenId": "10" + }, + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ] + }, + { + "id": "user-dangling", + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-distinct-on.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-distinct-on.json new file mode 100644 index 0000000000..4c571b95ed --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-distinct-on.json @@ -0,0 +1,59 @@ +{ + "role": "public", + "request": { + "query": "{ NftCollection(order_by: {id: asc}) { id tokens(distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}]) { id owner_id } } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-1", + "tokens": [ + { + "id": "tok-2", + "owner_id": "user-1" + }, + { + "id": "tok-3", + "owner_id": "user-2" + }, + { + "id": "tok-10", + "owner_id": "user-4" + } + ] + }, + { + "id": "coll-2", + "tokens": [ + { + "id": "tok-8", + "owner_id": "user \"quoted\" 🚀" + }, + { + "id": "tok-4", + "owner_id": "user-2" + }, + { + "id": "tok-5", + "owner_id": "user-3" + }, + { + "id": "tok-9", + "owner_id": "user-4" + }, + { + "id": "tok-6", + "owner_id": "user-missing" + } + ] + }, + { + "id": "coll-3", + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-empty.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-empty.json new file mode 100644 index 0000000000..c9abca6776 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-empty.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {id: {_eq: \"user-dangling\"}}) { id tokens(order_by: {id: asc}) { id } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-dangling", + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-nested-args.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-nested-args.json new file mode 100644 index 0000000000..8fd74b2d8e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-nested-args.json @@ -0,0 +1,65 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}) { id tokens(where: {tokenId: {_gte: 2}}, order_by: {tokenId: desc}, limit: 2) { id tokenId } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "tokens": [ + { + "id": "tok-8", + "tokenId": "8" + } + ] + }, + { + "id": "user-1", + "tokens": [ + { + "id": "tok-7", + "tokenId": "7" + } + ] + }, + { + "id": "user-2", + "tokens": [ + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-3", + "tokenId": "2" + } + ] + }, + { + "id": "user-3", + "tokens": [] + }, + { + "id": "user-4", + "tokens": [ + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "tok-10", + "tokenId": "10" + } + ] + }, + { + "id": "user-dangling", + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-nested-offset.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-nested-offset.json new file mode 100644 index 0000000000..89d6f3e420 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-array-nested-offset.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ NftCollection(order_by: {id: asc}) { id tokens(order_by: {tokenId: asc}, limit: 2, offset: 1) { id tokenId } } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-1", + "tokens": [ + { + "id": "tok-2", + "tokenId": "1" + }, + { + "id": "tok-3", + "tokenId": "2" + } + ] + }, + { + "id": "coll-2", + "tokens": [ + { + "id": "tok-8", + "tokenId": "8" + }, + { + "id": "tok-6", + "tokenId": "123456789" + } + ] + }, + { + "id": "coll-3", + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-circular-nesting.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-circular-nesting.json new file mode 100644 index 0000000000..fb9d44fa27 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-circular-nesting.json @@ -0,0 +1,51 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {id: {_eq: \"user-1\"}}) { id tokens(order_by: {id: asc}) { id owner { id tokens(order_by: {id: asc}, limit: 1) { id } } } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "owner": { + "id": "user-1", + "tokens": [ + { + "id": "tok-1" + } + ] + } + }, + { + "id": "tok-2", + "owner": { + "id": "user-1", + "tokens": [ + { + "id": "tok-1" + } + ] + } + }, + { + "id": "tok-7", + "owner": { + "id": "user-1", + "tokens": [ + { + "id": "tok-1" + } + ] + } + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-deep-nesting.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-deep-nesting.json new file mode 100644 index 0000000000..37f009bc2b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-deep-nesting.json @@ -0,0 +1,71 @@ +{ + "role": "public", + "request": { + "query": "{ NftCollection(order_by: {id: asc}, limit: 2) { id tokens(order_by: {id: asc}, limit: 3) { id owner { id gravatar { id displayName } } } } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-1", + "tokens": [ + { + "id": "tok-1", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "displayName": "First Grav" + } + } + }, + { + "id": "tok-10", + "owner": { + "id": "user-4", + "gravatar": null + } + }, + { + "id": "tok-2", + "owner": { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "displayName": "First Grav" + } + } + } + ] + }, + { + "id": "coll-2", + "tokens": [ + { + "id": "tok-4", + "owner": { + "id": "user-2", + "gravatar": { + "id": "grav-2", + "displayName": "Zwölf Grüße 中文" + } + } + }, + { + "id": "tok-5", + "owner": { + "id": "user-3", + "gravatar": null + } + }, + { + "id": "tok-6", + "owner": null + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-derived-from-id-typed-key.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-derived-from-id-typed-key.json new file mode 100644 index 0000000000..983af67d30 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-derived-from-id-typed-key.json @@ -0,0 +1,35 @@ +{ + "role": "public", + "request": { + "query": "{ C(order_by: {id: asc}) { id d(order_by: {id: asc}) { id c } } }" + }, + "status": 200, + "body": { + "data": { + "C": [ + { + "id": "c-1", + "d": [ + { + "id": "d-1", + "c": "c-1" + }, + { + "id": "d-2", + "c": "c-1" + } + ] + }, + { + "id": "c-2", + "d": [ + { + "id": "d-3", + "c": "c-2" + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-fragment-on-relationship.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-fragment-on-relationship.json new file mode 100644 index 0000000000..d9fbf52e00 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-fragment-on-relationship.json @@ -0,0 +1,68 @@ +{ + "role": "public", + "request": { + "query": "fragment TokenBits on Token { id tokenId collection { symbol } } { User(order_by: {id: asc}, limit: 3) { id tokens(order_by: {id: asc}) { ...TokenBits } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "tokens": [ + { + "id": "tok-8", + "tokenId": "8", + "collection": { + "symbol": "BÉTA" + } + } + ] + }, + { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "tokenId": "0", + "collection": { + "symbol": "ALPHA" + } + }, + { + "id": "tok-2", + "tokenId": "1", + "collection": { + "symbol": "ALPHA" + } + }, + { + "id": "tok-7", + "tokenId": "7", + "collection": null + } + ] + }, + { + "id": "user-2", + "tokens": [ + { + "id": "tok-3", + "tokenId": "2", + "collection": { + "symbol": "ALPHA" + } + }, + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000", + "collection": { + "symbol": "BÉTA" + } + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-object-basic.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-object-basic.json new file mode 100644 index 0000000000..f7ff160378 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-object-basic.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(order_by: {id: asc}) { id owner { id address accountType } } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-1", + "owner": { + "id": "user-1", + "address": "0xaaaa000000000000000000000000000000000001", + "accountType": "ADMIN" + } + }, + { + "id": "grav-2", + "owner": { + "id": "user-2", + "address": "0xaaaa000000000000000000000000000000000002", + "accountType": "USER" + } + }, + { + "id": "grav-3", + "owner": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-object-dangling.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-object-dangling.json new file mode 100644 index 0000000000..77ddcacec5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-object-dangling.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(where: {id: {_eq: \"grav-3\"}}) { id owner { id } } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-3", + "owner": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-object-nullable-fk.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-object-nullable-fk.json new file mode 100644 index 0000000000..48d2e2f17d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-object-nullable-fk.json @@ -0,0 +1,45 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}) { id gravatar { id displayName size } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "gravatar": null + }, + { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "displayName": "First Grav", + "size": "SMALL" + } + }, + { + "id": "user-2", + "gravatar": { + "id": "grav-2", + "displayName": "Zwölf Grüße 中文", + "size": "MEDIUM" + } + }, + { + "id": "user-3", + "gravatar": null + }, + { + "id": "user-4", + "gravatar": null + }, + { + "id": "user-dangling", + "gravatar": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-order-parent-by-child-aggregate-count.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-order-parent-by-child-aggregate-count.json new file mode 100644 index 0000000000..37ed92411e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-order-parent-by-child-aggregate-count.json @@ -0,0 +1,31 @@ +{ + "role": "admin", + "request": { + "query": "{ User(order_by: [{tokens_aggregate: {count: desc}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-4" + }, + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-3" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-order-parent-by-child-aggregate-max.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-order-parent-by-child-aggregate-max.json new file mode 100644 index 0000000000..255abf1531 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-order-parent-by-child-aggregate-max.json @@ -0,0 +1,22 @@ +{ + "role": "admin", + "request": { + "query": "{ NftCollection(order_by: [{tokens_aggregate: {max: {tokenId: desc_nulls_last}}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-2" + }, + { + "id": "coll-1" + }, + { + "id": "coll-3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-typename-in-nested.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-typename-in-nested.json new file mode 100644 index 0000000000..6fbdc48106 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-typename-in-nested.json @@ -0,0 +1,27 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(order_by: {id: asc}, limit: 2) { __typename owner { __typename id } } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "__typename": "Gravatar", + "owner": { + "__typename": "User", + "id": "user-1" + } + }, + { + "__typename": "Gravatar", + "owner": { + "__typename": "User", + "id": "user-2" + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rel-where-on-parent-and-child.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-where-on-parent-and-child.json new file mode 100644 index 0000000000..34ac579599 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rel-where-on-parent-and-child.json @@ -0,0 +1,52 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {tokens: {collection: {symbol: {_eq: \"ALPHA\"}}}}, order_by: {id: asc}) { id tokens(where: {collection: {symbol: {_eq: \"ALPHA\"}}}, order_by: {id: asc}) { id collection { symbol } } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "collection": { + "symbol": "ALPHA" + } + }, + { + "id": "tok-2", + "collection": { + "symbol": "ALPHA" + } + } + ] + }, + { + "id": "user-2", + "tokens": [ + { + "id": "tok-3", + "collection": { + "symbol": "ALPHA" + } + } + ] + }, + { + "id": "user-4", + "tokens": [ + { + "id": "tok-10", + "collection": { + "symbol": "ALPHA" + } + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-count-asc-empty-first.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-count-asc-empty-first.json new file mode 100644 index 0000000000..a3c690f0d6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-count-asc-empty-first.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ NftCollection(order_by: [{tokens_aggregate: {count: asc}}, {id: asc}]) { id currentSupply } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-3", + "currentSupply": 0 + }, + { + "id": "coll-1", + "currentSupply": 3 + }, + { + "id": "coll-2", + "currentSupply": 5 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-max-nulls-first.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-max-nulls-first.json new file mode 100644 index 0000000000..88abd811a6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-max-nulls-first.json @@ -0,0 +1,22 @@ +{ + "role": "public", + "request": { + "query": "{ NftCollection(order_by: [{tokens_aggregate: {max: {tokenId: asc_nulls_first}}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-3" + }, + { + "id": "coll-1" + }, + { + "id": "coll-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-min-asc-nulls-first.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-min-asc-nulls-first.json new file mode 100644 index 0000000000..7164c33e51 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-min-asc-nulls-first.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: [{tokens_aggregate: {min: {tokenId: asc_nulls_first}}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-dangling" + }, + { + "id": "user-3" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-sum-desc-nulls-last.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-sum-desc-nulls-last.json new file mode 100644 index 0000000000..4fd8ad26f3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-agg-order-sum-desc-nulls-last.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: [{tokens_aggregate: {sum: {tokenId: desc_nulls_last}}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-4" + }, + { + "id": "user-2" + }, + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-3" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-alias-conflict-rel-vs-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-alias-conflict-rel-vs-column.json new file mode 100644 index 0000000000..1a24669c15 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-alias-conflict-rel-vs-column.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ Token(limit: 1) { owner: owner_id owner { id } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "selection of both 'owner_id' and 'owner' specify the same response name, 'owner'", + "extensions": { + "path": "$.selectionSet.Token.selectionSet", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-alias-swap-column-and-rel.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-alias-swap-column-and-rel.json new file mode 100644 index 0000000000..bc033586eb --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-alias-swap-column-and-rel.json @@ -0,0 +1,61 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: {id: asc}, limit: 4) { id owner: owner_id owner_id: owner { id } collection: collection_id collection_id: collection { id name } } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-1", + "owner": "user-1", + "owner_id": { + "id": "user-1" + }, + "collection": "coll-1", + "collection_id": { + "id": "coll-1", + "name": "Alpha Apes" + } + }, + { + "id": "tok-10", + "owner": "user-4", + "owner_id": { + "id": "user-4" + }, + "collection": "coll-1", + "collection_id": { + "id": "coll-1", + "name": "Alpha Apes" + } + }, + { + "id": "tok-2", + "owner": "user-1", + "owner_id": { + "id": "user-1" + }, + "collection": "coll-1", + "collection_id": { + "id": "coll-1", + "name": "Alpha Apes" + } + }, + { + "id": "tok-3", + "owner": "user-2", + "owner_id": { + "id": "user-2" + }, + "collection": "coll-1", + "collection_id": { + "id": "coll-1", + "name": "Alpha Apes" + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-alias-user-gravatar-shadow.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-alias-user-gravatar-shadow.json new file mode 100644 index 0000000000..aa011218f6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-alias-user-gravatar-shadow.json @@ -0,0 +1,52 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 3) { id gravatar: gravatar_id gravatar_id: gravatar { id displayName } tokens: address address: tokens(order_by: {id: asc}, limit: 1) { id } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "gravatar": null, + "gravatar_id": null, + "tokens": "0xaaaa000000000000000000000000000000000005", + "address": [ + { + "id": "tok-8" + } + ] + }, + { + "id": "user-1", + "gravatar": "grav-1", + "gravatar_id": { + "id": "grav-1", + "displayName": "First Grav" + }, + "tokens": "0xaaaa000000000000000000000000000000000001", + "address": [ + { + "id": "tok-1" + } + ] + }, + { + "id": "user-2", + "gravatar": "grav-2", + "gravatar_id": { + "id": "grav-2", + "displayName": "Zwölf Grüße 中文" + }, + "tokens": "0xaaaa000000000000000000000000000000000002", + "address": [ + { + "id": "tok-3" + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-child-all-args-collection-tokens.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-child-all-args-collection-tokens.json new file mode 100644 index 0000000000..af8e84bd16 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-child-all-args-collection-tokens.json @@ -0,0 +1,36 @@ +{ + "role": "public", + "request": { + "query": "{ NftCollection(order_by: {id: asc}) { id tokens(where: {owner: {accountType: {_eq: \"USER\"}}}, distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}, {id: asc}], limit: 2, offset: 1) { id owner_id tokenId } } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-1", + "tokens": [] + }, + { + "id": "coll-2", + "tokens": [ + { + "id": "tok-4", + "owner_id": "user-2", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-5", + "owner_id": "user-3", + "tokenId": "-5" + } + ] + }, + { + "id": "coll-3", + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-child-all-args-user-tokens.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-child-all-args-user-tokens.json new file mode 100644 index 0000000000..b8ac1e86db --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-child-all-args-user-tokens.json @@ -0,0 +1,55 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}) { id tokens(where: {tokenId: {_gte: 0}}, distinct_on: collection_id, order_by: [{collection_id: asc}, {tokenId: desc}, {id: asc}], limit: 2, offset: 1) { id collection_id tokenId } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "tokens": [] + }, + { + "id": "user-1", + "tokens": [ + { + "id": "tok-7", + "collection_id": "coll-missing", + "tokenId": "7" + } + ] + }, + { + "id": "user-2", + "tokens": [ + { + "id": "tok-4", + "collection_id": "coll-2", + "tokenId": "1000000000000000000000000000000" + } + ] + }, + { + "id": "user-3", + "tokens": [] + }, + { + "id": "user-4", + "tokens": [ + { + "id": "tok-9", + "collection_id": "coll-2", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ] + }, + { + "id": "user-dangling", + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-child-window-beyond-rows.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-child-window-beyond-rows.json new file mode 100644 index 0000000000..a3588d477a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-child-window-beyond-rows.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {id: {_in: [\"user-1\", \"user-2\"]}}, order_by: {id: asc}) { id tokens(order_by: {id: asc}, limit: 3, offset: 50) { id } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1", + "tokens": [] + }, + { + "id": "user-2", + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-and-inside-rel.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-and-inside-rel.json new file mode 100644 index 0000000000..3d644144d0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-and-inside-rel.json @@ -0,0 +1,22 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {tokens: {_and: [{tokenId: {_gte: 0}}, {collection: {symbol: {_eq: \"BÉTA\"}}}]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-2" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-and-parent-child.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-and-parent-child.json new file mode 100644 index 0000000000..87dc486cd8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-and-parent-child.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {_and: [{accountType: {_eq: \"ADMIN\"}}, {tokens: {collection: {symbol: {_eq: \"ALPHA\"}}}}]}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-not-inside-rel.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-not-inside-rel.json new file mode 100644 index 0000000000..5e8d2ee369 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-not-inside-rel.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {tokens: {_not: {collection: {}}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-or-three-branches.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-or-three-branches.json new file mode 100644 index 0000000000..34c221bdf2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-or-three-branches.json @@ -0,0 +1,49 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {_or: [{tokenId: {_lt: 0}}, {owner: {accountType: {_eq: \"ADMIN\"}}}, {collection: {name: {_eq: \"\"}}}]}, order_by: {id: asc}) { id tokenId owner_id collection_id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-1", + "tokenId": "0", + "owner_id": "user-1", + "collection_id": "coll-1" + }, + { + "id": "tok-10", + "tokenId": "10", + "owner_id": "user-4", + "collection_id": "coll-1" + }, + { + "id": "tok-2", + "tokenId": "1", + "owner_id": "user-1", + "collection_id": "coll-1" + }, + { + "id": "tok-5", + "tokenId": "-5", + "owner_id": "user-3", + "collection_id": "coll-2" + }, + { + "id": "tok-7", + "tokenId": "7", + "owner_id": "user-1", + "collection_id": "coll-missing" + }, + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999", + "owner_id": "user-4", + "collection_id": "coll-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-or-two-rel-paths.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-or-two-rel-paths.json new file mode 100644 index 0000000000..77d37f27ec --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-cross-or-two-rel-paths.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {_or: [{gravatar: {size: {_eq: \"MEDIUM\"}}}, {tokens: {tokenId: {_eq: \"9999999999999999999999999999999999999999999999999999999999999999999999999999\"}}}]}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-2" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-a-b.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-a-b.json new file mode 100644 index 0000000000..4c458d7fa0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-a-b.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ A_by_pk(id: \"a-4\") { id b_id b { id c_id } } }" + }, + "status": 200, + "body": { + "data": { + "A_by_pk": { + "id": "a-4", + "b_id": "b-missing", + "b": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-b-c-all-rows.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-b-c-all-rows.json new file mode 100644 index 0000000000..4e13c3324a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-b-c-all-rows.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ B(order_by: {id: asc}) { id c_id c { id stringThatIsMirroredToA } } }" + }, + "status": 200, + "body": { + "data": { + "B": [ + { + "id": "b-1", + "c_id": "c-1", + "c": { + "id": "c-1", + "stringThatIsMirroredToA": "mirror-1" + } + }, + { + "id": "b-2", + "c_id": null, + "c": null + }, + { + "id": "b-3", + "c_id": "c-missing", + "c": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-d-via-rel-vs-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-d-via-rel-vs-column.json new file mode 100644 index 0000000000..ea12a95e82 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-d-via-rel-vs-column.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ viaRel: C(where: {d: {id: {_eq: \"d-4\"}}}, order_by: {id: asc}) { id } viaColumn: D(where: {c: {_eq: \"c-missing\"}}, order_by: {id: asc}) { id c } }" + }, + "status": 200, + "body": { + "data": { + "viaRel": [], + "viaColumn": [ + { + "id": "d-4", + "c": "c-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-gravatar-owner.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-gravatar-owner.json new file mode 100644 index 0000000000..311dd8a7b1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-gravatar-owner.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar_by_pk(id: \"grav-3\") { id owner_id owner { id address } } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar_by_pk": { + "id": "grav-3", + "owner_id": "user-missing", + "owner": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-token-collection.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-token-collection.json new file mode 100644 index 0000000000..ec84dbffad --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-token-collection.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ Token_by_pk(id: \"tok-7\") { id collection_id collection { id name } } }" + }, + "status": 200, + "body": { + "data": { + "Token_by_pk": { + "id": "tok-7", + "collection_id": "coll-missing", + "collection": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-token-owner.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-token-owner.json new file mode 100644 index 0000000000..248ba4e942 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-token-owner.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ Token_by_pk(id: \"tok-6\") { id owner_id owner { id address } } }" + }, + "status": 200, + "body": { + "data": { + "Token_by_pk": { + "id": "tok-6", + "owner_id": "user-missing", + "owner": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-user-gravatar.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-user-gravatar.json new file mode 100644 index 0000000000..74495ce1ac --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-dangling-user-gravatar.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"user-dangling\") { id gravatar_id gravatar { id displayName } } }" + }, + "status": 200, + "body": { + "data": { + "User_by_pk": { + "id": "user-dangling", + "gravatar_id": "grav-missing", + "gravatar": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-deep-self-nesting-depth7.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-deep-self-nesting-depth7.json new file mode 100644 index 0000000000..9ef5dbe627 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-deep-self-nesting-depth7.json @@ -0,0 +1,122 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {id: {_eq: \"user-1\"}}) { id tokens(order_by: {id: asc}, limit: 2) { id owner { id tokens(order_by: {id: asc}, limit: 2) { id owner { id tokens(order_by: {id: asc}, limit: 2) { id tokenId owner { id } } } } } } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "owner": { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "owner": { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "tokenId": "0", + "owner": { + "id": "user-1" + } + }, + { + "id": "tok-2", + "tokenId": "1", + "owner": { + "id": "user-1" + } + } + ] + } + }, + { + "id": "tok-2", + "owner": { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "tokenId": "0", + "owner": { + "id": "user-1" + } + }, + { + "id": "tok-2", + "tokenId": "1", + "owner": { + "id": "user-1" + } + } + ] + } + } + ] + } + }, + { + "id": "tok-2", + "owner": { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "owner": { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "tokenId": "0", + "owner": { + "id": "user-1" + } + }, + { + "id": "tok-2", + "tokenId": "1", + "owner": { + "id": "user-1" + } + } + ] + } + }, + { + "id": "tok-2", + "owner": { + "id": "user-1", + "tokens": [ + { + "id": "tok-1", + "tokenId": "0", + "owner": { + "id": "user-1" + } + }, + { + "id": "tok-2", + "tokenId": "1", + "owner": { + "id": "user-1" + } + } + ] + } + } + ] + } + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-deep-where-self-referential.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-deep-where-self-referential.json new file mode 100644 index 0000000000..42ba369008 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-deep-where-self-referential.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {tokens: {owner: {tokens: {owner: {tokens: {tokenId: {_eq: \"8\"}}}}}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-b-a-pair.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-b-a-pair.json new file mode 100644 index 0000000000..90d8a3f67b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-b-a-pair.json @@ -0,0 +1,24 @@ +{ + "role": "public", + "request": { + "query": "{ any: B(where: {a: {}}, order_by: {id: asc}) { id } none: B(where: {_not: {a: {}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "any": [ + { + "id": "b-1" + }, + { + "id": "b-2" + } + ], + "none": [ + { + "id": "b-3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-bare-vs-predicate.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-bare-vs-predicate.json new file mode 100644 index 0000000000..a247f63262 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-bare-vs-predicate.json @@ -0,0 +1,24 @@ +{ + "role": "public", + "request": { + "query": "{ bare: NftCollection(where: {tokens: {}}, order_by: {id: asc}) { id } withPred: NftCollection(where: {tokens: {tokenId: {_gt: 1000}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "bare": [ + { + "id": "coll-1" + }, + { + "id": "coll-2" + } + ], + "withPred": [ + { + "id": "coll-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-c-d-pair.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-c-d-pair.json new file mode 100644 index 0000000000..3d24177cd8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-c-d-pair.json @@ -0,0 +1,20 @@ +{ + "role": "public", + "request": { + "query": "{ any: C(where: {d: {}}, order_by: {id: asc}) { id } none: C(where: {_not: {d: {}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "any": [ + { + "id": "c-1" + }, + { + "id": "c-2" + } + ], + "none": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-collection-tokens-pair.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-collection-tokens-pair.json new file mode 100644 index 0000000000..df492571c8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-collection-tokens-pair.json @@ -0,0 +1,27 @@ +{ + "role": "public", + "request": { + "query": "{ any: NftCollection(where: {tokens: {}}, order_by: {id: asc}) { id name } none: NftCollection(where: {_not: {tokens: {}}}, order_by: {id: asc}) { id name } }" + }, + "status": 200, + "body": { + "data": { + "any": [ + { + "id": "coll-1", + "name": "Alpha Apes" + }, + { + "id": "coll-2", + "name": "Béta Bots 🤖" + } + ], + "none": [ + { + "id": "coll-3", + "name": "" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-user-tokens-pair.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-user-tokens-pair.json new file mode 100644 index 0000000000..e7cd1b0f05 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-exists-user-tokens-pair.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ any: User(where: {tokens: {}}, order_by: {id: asc}) { id } none: User(where: {_not: {tokens: {}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "any": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + } + ], + "none": [ + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-a-b-a-siblings.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-a-b-a-siblings.json new file mode 100644 index 0000000000..b039504096 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-a-b-a-siblings.json @@ -0,0 +1,56 @@ +{ + "role": "public", + "request": { + "query": "{ A(order_by: {id: asc}) { id b { id a(order_by: {id: asc}) { id } } } }" + }, + "status": 200, + "body": { + "data": { + "A": [ + { + "id": "a-1", + "b": { + "id": "b-1", + "a": [ + { + "id": "a-1" + }, + { + "id": "a-2" + } + ] + } + }, + { + "id": "a-2", + "b": { + "id": "b-1", + "a": [ + { + "id": "a-1" + }, + { + "id": "a-2" + } + ] + } + }, + { + "id": "a-3", + "b": { + "id": "b-2", + "a": [ + { + "id": "a-3" + } + ] + } + }, + { + "id": "a-4", + "b": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-a-b-c-d.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-a-b-c-d.json new file mode 100644 index 0000000000..25351bb842 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-a-b-c-d.json @@ -0,0 +1,68 @@ +{ + "role": "public", + "request": { + "query": "{ A(order_by: {id: asc}) { id optionalStringToTestLinkedEntities b { id c { id stringThatIsMirroredToA d(order_by: {id: asc}) { id c } } } } }" + }, + "status": 200, + "body": { + "data": { + "A": [ + { + "id": "a-1", + "optionalStringToTestLinkedEntities": "linked", + "b": { + "id": "b-1", + "c": { + "id": "c-1", + "stringThatIsMirroredToA": "mirror-1", + "d": [ + { + "id": "d-1", + "c": "c-1" + }, + { + "id": "d-2", + "c": "c-1" + } + ] + } + } + }, + { + "id": "a-2", + "optionalStringToTestLinkedEntities": null, + "b": { + "id": "b-1", + "c": { + "id": "c-1", + "stringThatIsMirroredToA": "mirror-1", + "d": [ + { + "id": "d-1", + "c": "c-1" + }, + { + "id": "d-2", + "c": "c-1" + } + ] + } + } + }, + { + "id": "a-3", + "optionalStringToTestLinkedEntities": "", + "b": { + "id": "b-2", + "c": null + } + }, + { + "id": "a-4", + "optionalStringToTestLinkedEntities": "dangling b", + "b": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-b-both-directions.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-b-both-directions.json new file mode 100644 index 0000000000..c057c0d8cc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-b-both-directions.json @@ -0,0 +1,58 @@ +{ + "role": "public", + "request": { + "query": "{ B(order_by: {id: asc}) { id a(order_by: {id: asc}) { id b { id } } c { id d(order_by: {id: asc}) { id } } } }" + }, + "status": 200, + "body": { + "data": { + "B": [ + { + "id": "b-1", + "a": [ + { + "id": "a-1", + "b": { + "id": "b-1" + } + }, + { + "id": "a-2", + "b": { + "id": "b-1" + } + } + ], + "c": { + "id": "c-1", + "d": [ + { + "id": "d-1" + }, + { + "id": "d-2" + } + ] + } + }, + { + "id": "b-2", + "a": [ + { + "id": "a-3", + "b": { + "id": "b-2" + } + } + ], + "c": null + }, + { + "id": "b-3", + "a": [], + "c": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-c-both-directions.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-c-both-directions.json new file mode 100644 index 0000000000..ed3078eca0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-c-both-directions.json @@ -0,0 +1,50 @@ +{ + "role": "public", + "request": { + "query": "{ C(order_by: {id: asc}) { id a { id b { id c { id } } } d(order_by: {id: asc}) { id } } }" + }, + "status": 200, + "body": { + "data": { + "C": [ + { + "id": "c-1", + "a": { + "id": "a-1", + "b": { + "id": "b-1", + "c": { + "id": "c-1" + } + } + }, + "d": [ + { + "id": "d-1" + }, + { + "id": "d-2" + } + ] + }, + { + "id": "c-2", + "a": { + "id": "a-2", + "b": { + "id": "b-1", + "c": { + "id": "c-1" + } + } + }, + "d": [ + { + "id": "d-3" + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-d-plain-column-filter.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-d-plain-column-filter.json new file mode 100644 index 0000000000..3d35debfce --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-multihop-d-plain-column-filter.json @@ -0,0 +1,26 @@ +{ + "role": "public", + "request": { + "query": "{ C(where: {d: {c: {_eq: \"c-1\"}}}, order_by: {id: asc}) { id d(where: {c: {_eq: \"c-1\"}}, order_by: {id: asc}) { id c } } }" + }, + "status": 200, + "body": { + "data": { + "C": [ + { + "id": "c-1", + "d": [ + { + "id": "d-1", + "c": "c-1" + }, + { + "id": "d-2", + "c": "c-1" + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-exists-a-b-pair.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-exists-a-b-pair.json new file mode 100644 index 0000000000..d69aeadf23 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-exists-a-b-pair.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ has: A(where: {b: {}}, order_by: {id: asc}) { id b_id } lacks: A(where: {_not: {b: {}}}, order_by: {id: asc}) { id b_id } }" + }, + "status": 200, + "body": { + "data": { + "has": [ + { + "id": "a-1", + "b_id": "b-1" + }, + { + "id": "a-2", + "b_id": "b-1" + }, + { + "id": "a-3", + "b_id": "b-2" + } + ], + "lacks": [ + { + "id": "a-4", + "b_id": "b-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-exists-gravatar-pair.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-exists-gravatar-pair.json new file mode 100644 index 0000000000..a9406cecf4 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-exists-gravatar-pair.json @@ -0,0 +1,39 @@ +{ + "role": "public", + "request": { + "query": "{ has: User(where: {gravatar: {}}, order_by: {id: asc}) { id gravatar_id } lacks: User(where: {_not: {gravatar: {}}}, order_by: {id: asc}) { id gravatar_id } }" + }, + "status": 200, + "body": { + "data": { + "has": [ + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + } + ], + "lacks": [ + { + "id": "user \"quoted\" 🚀", + "gravatar_id": null + }, + { + "id": "user-3", + "gravatar_id": null + }, + { + "id": "user-4", + "gravatar_id": null + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-exists-vs-fk-not-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-exists-vs-fk-not-null.json new file mode 100644 index 0000000000..266847b1b3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-exists-vs-fk-not-null.json @@ -0,0 +1,30 @@ +{ + "role": "public", + "request": { + "query": "{ exists: User(where: {gravatar: {}}, order_by: {id: asc}) { id } fkNotNull: User(where: {gravatar_id: {_is_null: false}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "exists": [ + { + "id": "user-1" + }, + { + "id": "user-2" + } + ], + "fkNotNull": [ + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-b-c.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-b-c.json new file mode 100644 index 0000000000..d2ac99a04c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-b-c.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ B(where: {_not: {c: {}}}, order_by: {id: asc}) { id c_id } }" + }, + "status": 200, + "body": { + "data": { + "B": [ + { + "id": "b-2", + "c_id": null + }, + { + "id": "b-3", + "c_id": "c-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-gravatar-owner.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-gravatar-owner.json new file mode 100644 index 0000000000..f273e49cc7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-gravatar-owner.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(where: {_not: {owner: {}}}, order_by: {id: asc}) { id owner_id } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-3", + "owner_id": "user-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-token-collection.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-token-collection.json new file mode 100644 index 0000000000..b74f42ca46 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-token-collection.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {_not: {collection: {}}}, order_by: {id: asc}) { id collection_id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-7", + "collection_id": "coll-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-token-owner.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-token-owner.json new file mode 100644 index 0000000000..87d3eba1bc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-object-not-exists-token-owner.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {_not: {owner: {}}}, order_by: {id: asc}) { id owner_id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-6", + "owner_id": "user-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-order-object-rel-dangling-nulls-first.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-order-object-rel-dangling-nulls-first.json new file mode 100644 index 0000000000..f6cebfb661 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-order-object-rel-dangling-nulls-first.json @@ -0,0 +1,53 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: [{collection: {name: asc_nulls_first}}, {id: asc}]) { id collection_id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-7", + "collection_id": "coll-missing" + }, + { + "id": "tok-1", + "collection_id": "coll-1" + }, + { + "id": "tok-10", + "collection_id": "coll-1" + }, + { + "id": "tok-2", + "collection_id": "coll-1" + }, + { + "id": "tok-3", + "collection_id": "coll-1" + }, + { + "id": "tok-4", + "collection_id": "coll-2" + }, + { + "id": "tok-5", + "collection_id": "coll-2" + }, + { + "id": "tok-6", + "collection_id": "coll-2" + }, + { + "id": "tok-8", + "collection_id": "coll-2" + }, + { + "id": "tok-9", + "collection_id": "coll-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-same-table-b-self-join.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-same-table-b-self-join.json new file mode 100644 index 0000000000..1486632e8e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-same-table-b-self-join.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ A(where: {b: {a: {id: {_eq: \"a-2\"}}}}, order_by: {id: asc}) { id b_id } }" + }, + "status": 200, + "body": { + "data": { + "A": [ + { + "id": "a-1", + "b_id": "b-1" + }, + { + "id": "a-2", + "b_id": "b-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-same-table-token-and-sibling.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-same-table-token-and-sibling.json new file mode 100644 index 0000000000..b20aa0734e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-same-table-token-and-sibling.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {_and: [{owner: {accountType: {_eq: \"ADMIN\"}}}, {collection: {tokens: {owner: {accountType: {_eq: \"USER\"}}}}}]}, order_by: {id: asc}) { id owner_id collection_id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-1", + "owner_id": "user-1", + "collection_id": "coll-1" + }, + { + "id": "tok-10", + "owner_id": "user-4", + "collection_id": "coll-1" + }, + { + "id": "tok-2", + "owner_id": "user-1", + "collection_id": "coll-1" + }, + { + "id": "tok-9", + "owner_id": "user-4", + "collection_id": "coll-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/rm-same-table-two-paths.json b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-same-table-two-paths.json new file mode 100644 index 0000000000..b0ea696594 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/rm-same-table-two-paths.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {tokens: {collection: {tokens: {owner: {accountType: {_eq: \"USER\"}}}}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-all-non-array-full.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-all-non-array-full.json new file mode 100644 index 0000000000..f85bd00114 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-all-non-array-full.json @@ -0,0 +1,173 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(order_by: {id: asc}) { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-1", + "string": "plain", + "optString": "present", + "int_": 1, + "optInt": 10, + "float_": "1.5", + "optFloat": "2.5", + "bool": true, + "optBool": true, + "bigInt": "100", + "optBigInt": "200", + "bigDecimal": "1.25", + "optBigDecimal": "3.75", + "bigDecimalWithConfig": "1.00000001", + "enumField": "ADMIN", + "optEnumField": "USER", + "timestamp": "2024-01-15T12:34:56.789+00:00", + "optTimestamp": "2024-01-15T12:34:56.789123+00:00" + }, + { + "id": "scalar-empty", + "string": "", + "optString": "", + "int_": 4, + "optInt": 0, + "float_": "-0.5", + "optFloat": "0", + "bool": true, + "optBool": false, + "bigInt": "10", + "optBigInt": "0", + "bigDecimal": "100", + "optBigDecimal": "0", + "bigDecimalWithConfig": "0.00000001", + "enumField": "USER", + "optEnumField": "ADMIN", + "timestamp": "2024-07-04T00:00:00.1+00:00", + "optTimestamp": "2024-07-04T00:00:00.12+00:00" + }, + { + "id": "scalar-extremes", + "string": "extremes", + "optString": "x", + "int_": 2147483647, + "optInt": -2147483648, + "float_": "1.7976931348623157e+308", + "optFloat": "5e-324", + "bool": true, + "optBool": false, + "bigInt": "9999999999999999999999999999999999999999999999999999999999999999999999999999", + "optBigInt": "-9999999999999999999999999999999999999999999999999999999999999999999999999999", + "bigDecimal": "12345678901234567890.123456789", + "optBigDecimal": "-0.000000001", + "bigDecimalWithConfig": "99.99999999", + "enumField": "ADMIN", + "optEnumField": "ADMIN", + "timestamp": "9999-12-31T23:59:59.999999+00:00", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + }, + { + "id": "scalar-neg-inf", + "string": "neg inf", + "optString": null, + "int_": -2, + "optInt": null, + "float_": "-Infinity", + "optFloat": "-0", + "bool": true, + "optBool": null, + "bigInt": "-1", + "optBigInt": null, + "bigDecimal": "-1.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "-0.00000001", + "enumField": "USER", + "optEnumField": null, + "timestamp": "2024-07-01T00:00:00+00:00", + "optTimestamp": null + }, + { + "id": "scalar-nulls", + "string": "has nulls", + "optString": null, + "int_": 0, + "optInt": null, + "float_": "0", + "optFloat": null, + "bool": false, + "optBool": null, + "bigInt": "0", + "optBigInt": null, + "bigDecimal": "0", + "optBigDecimal": null, + "bigDecimalWithConfig": "0.00000000", + "enumField": "USER", + "optEnumField": null, + "timestamp": "1970-01-01T00:00:00+00:00", + "optTimestamp": null + }, + { + "id": "scalar-quotes", + "string": "with \"double\" and 'single' and back\\slash and\nnewline and\ttab", + "optString": "end", + "int_": 3, + "optInt": 3, + "float_": "0.1", + "optFloat": "0.2", + "bool": false, + "optBool": false, + "bigInt": "7", + "optBigInt": "8", + "bigDecimal": "0.5", + "optBigDecimal": "0.5", + "bigDecimalWithConfig": "3.00000000", + "enumField": "ADMIN", + "optEnumField": "USER", + "timestamp": "2024-03-10T10:00:00+00:00", + "optTimestamp": "2024-03-10T10:00:00+00:00" + }, + { + "id": "scalar-special-float", + "string": "inf and nan", + "optString": null, + "int_": -1, + "optInt": null, + "float_": "Infinity", + "optFloat": "NaN", + "bool": false, + "optBool": null, + "bigInt": "1", + "optBigInt": null, + "bigDecimal": "1.1000", + "optBigDecimal": null, + "bigDecimalWithConfig": "0.50000000", + "enumField": "USER", + "optEnumField": null, + "timestamp": "2000-02-29T00:00:00+00:00", + "optTimestamp": null + }, + { + "id": "scalar-unicode", + "string": "héllo wörld 中文测试 🚀🎉", + "optString": "emoji 🤖", + "int_": 7, + "optInt": 7, + "float_": "-3.14159", + "optFloat": "2.718281828459045", + "bool": true, + "optBool": true, + "bigInt": "42", + "optBigInt": "-42", + "bigDecimal": "3.14000", + "optBigDecimal": "0.00000", + "bigDecimalWithConfig": "2.50000000", + "enumField": "USER", + "optEnumField": "USER", + "timestamp": "2024-12-25T13:00:00+00:00", + "optTimestamp": "2024-12-26T02:30:00+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-all-types-full.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-all-types-full.json new file mode 100644 index 0000000000..6017677e19 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-all-types-full.json @@ -0,0 +1,338 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(order_by: {id: asc}) { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1", + "string": "first", + "optString": "opt", + "arrayOfStrings": [ + "one", + "two", + "three" + ], + "int_": 1, + "optInt": 2, + "arrayOfInts": [ + 1, + 2, + 3 + ], + "float_": "1.5", + "optFloat": "2.5", + "arrayOfFloats": [ + 1.5, + 2.5, + -3.5 + ], + "bool": true, + "optBool": false, + "bigInt": "1000", + "optBigInt": "2000", + "arrayOfBigInts": [ + "1", + "2", + "3" + ], + "bigDecimal": "10.5", + "optBigDecimal": "20.5", + "bigDecimalWithConfig": "1.12345678", + "arrayOfBigDecimals": [ + "1.5", + "2.25" + ], + "timestamp": "2024-01-01T00:00:00+00:00", + "optTimestamp": "2024-01-02T00:00:00+00:00", + "json": { + "n": 1, + "kind": "object", + "nested": { + "a": [ + 1, + 2 + ] + } + }, + "enumField": "ADMIN", + "optEnumField": "USER" + }, + { + "id": "all-array-edge", + "string": "array edges", + "optString": "x", + "arrayOfStrings": [ + "with,comma", + "with}brace", + "with\"quote", + "with'single", + "", + " leading space", + "emoji 🚀", + "back\\slash" + ], + "int_": -1, + "optInt": -2, + "arrayOfInts": [ + -2147483648, + 0, + 2147483647 + ], + "float_": "-1.5", + "optFloat": null, + "arrayOfFloats": [ + 0, + -0.5 + ], + "bool": true, + "optBool": true, + "bigInt": "-1", + "optBigInt": "1", + "arrayOfBigInts": [ + "-99999999999999999999999999999999999999", + "0", + "99999999999999999999999999999999999999" + ], + "bigDecimal": "-0.5", + "optBigDecimal": "0.5", + "bigDecimalWithConfig": "-1.00000001", + "arrayOfBigDecimals": [ + "-1.5", + "0.0", + "1.500" + ], + "timestamp": "2024-05-05T05:05:05.55555+00:00", + "optTimestamp": "2024-05-05T05:05:05.555555+00:00", + "json": [ + 1, + "two", + null, + true, + { + "k": "v" + }, + [ + 2.5 + ] + ], + "enumField": "ADMIN", + "optEnumField": "ADMIN" + }, + { + "id": "all-empty-arrays", + "string": "empty", + "optString": null, + "arrayOfStrings": [], + "int_": 0, + "optInt": null, + "arrayOfInts": [], + "float_": "0", + "optFloat": null, + "arrayOfFloats": [], + "bool": false, + "optBool": null, + "bigInt": "0", + "optBigInt": null, + "arrayOfBigInts": [], + "bigDecimal": "0", + "optBigDecimal": null, + "bigDecimalWithConfig": "0.00000000", + "arrayOfBigDecimals": [], + "timestamp": "2024-01-01T00:00:00+00:00", + "optTimestamp": null, + "json": {}, + "enumField": "USER", + "optEnumField": null + }, + { + "id": "all-json-bool", + "string": "json scalar bool", + "optString": null, + "arrayOfStrings": [ + "e" + ], + "int_": 9, + "optInt": null, + "arrayOfInts": [ + 9 + ], + "float_": "9.5", + "optFloat": null, + "arrayOfFloats": [ + 9.5 + ], + "bool": true, + "optBool": null, + "bigInt": "9", + "optBigInt": null, + "arrayOfBigInts": [ + "9" + ], + "bigDecimal": "9.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "9.00000000", + "arrayOfBigDecimals": [ + "9.5" + ], + "timestamp": "2024-02-06T02:02:02+00:00", + "optTimestamp": null, + "json": false, + "enumField": "USER", + "optEnumField": null + }, + { + "id": "all-json-null", + "string": "jsonb null literal", + "optString": null, + "arrayOfStrings": [ + "c" + ], + "int_": 7, + "optInt": null, + "arrayOfInts": [ + 7 + ], + "float_": "7.5", + "optFloat": null, + "arrayOfFloats": [ + 7.5 + ], + "bool": true, + "optBool": null, + "bigInt": "7", + "optBigInt": null, + "arrayOfBigInts": [ + "7" + ], + "bigDecimal": "7.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "7.00000000", + "arrayOfBigDecimals": [ + "7.5" + ], + "timestamp": "2024-02-04T02:02:02+00:00", + "optTimestamp": null, + "json": null, + "enumField": "ADMIN", + "optEnumField": null + }, + { + "id": "all-json-number", + "string": "json scalar number", + "optString": null, + "arrayOfStrings": [ + "b" + ], + "int_": 6, + "optInt": null, + "arrayOfInts": [ + 6 + ], + "float_": "6.5", + "optFloat": null, + "arrayOfFloats": [ + 6.5 + ], + "bool": false, + "optBool": null, + "bigInt": "6", + "optBigInt": null, + "arrayOfBigInts": [ + "6" + ], + "bigDecimal": "6.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "6.00000000", + "arrayOfBigDecimals": [ + "6.5" + ], + "timestamp": "2024-02-03T02:02:02+00:00", + "optTimestamp": null, + "json": 1.2345678901234568e+29, + "enumField": "USER", + "optEnumField": null + }, + { + "id": "all-json-string", + "string": "json scalar string", + "optString": null, + "arrayOfStrings": [ + "a" + ], + "int_": 5, + "optInt": 5, + "arrayOfInts": [ + 5 + ], + "float_": "5.5", + "optFloat": "5.5", + "arrayOfFloats": [ + 5.5 + ], + "bool": true, + "optBool": null, + "bigInt": "5", + "optBigInt": "5", + "arrayOfBigInts": [ + "5" + ], + "bigDecimal": "5.5", + "optBigDecimal": "5.5", + "bigDecimalWithConfig": "5.00000000", + "arrayOfBigDecimals": [ + "5.5" + ], + "timestamp": "2024-02-02T02:02:02+00:00", + "optTimestamp": null, + "json": "just a string", + "enumField": "USER", + "optEnumField": null + }, + { + "id": "all-json-unicode", + "string": "json unicode", + "optString": null, + "arrayOfStrings": [ + "d" + ], + "int_": 8, + "optInt": null, + "arrayOfInts": [ + 8 + ], + "float_": "8.5", + "optFloat": null, + "arrayOfFloats": [ + 8.5 + ], + "bool": false, + "optBool": null, + "bigInt": "8", + "optBigInt": null, + "arrayOfBigInts": [ + "8" + ], + "bigDecimal": "8.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "8.00000000", + "arrayOfBigDecimals": [ + "8.5" + ], + "timestamp": "2024-02-05T02:02:02+00:00", + "optTimestamp": null, + "json": { + "esc": "a\"b\\c\nd", + "num": 1e+100, + "héllo": "wörld 🚀" + }, + "enumField": "USER", + "optEnumField": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-bigdecimal-trailing-zeros.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-bigdecimal-trailing-zeros.json new file mode 100644 index 0000000000..98786dc1fe --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-bigdecimal-trailing-zeros.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithBigDecimal(order_by: {id: asc}) { id bigDecimal } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithBigDecimal": [ + { + "id": "bd-1", + "bigDecimal": "0" + }, + { + "id": "bd-2", + "bigDecimal": "1.10" + }, + { + "id": "bd-3", + "bigDecimal": "-1.10" + }, + { + "id": "bd-4", + "bigDecimal": "123456789.123456789" + }, + { + "id": "bd-5", + "bigDecimal": "0.000000000000000001" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-empty-arrays.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-empty-arrays.json new file mode 100644 index 0000000000..b225657816 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-empty-arrays.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {id: {_eq: \"all-empty-arrays\"}}) { id arrayOfStrings arrayOfInts arrayOfFloats arrayOfBigInts arrayOfBigDecimals } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-empty-arrays", + "arrayOfStrings": [], + "arrayOfInts": [], + "arrayOfFloats": [], + "arrayOfBigInts": [], + "arrayOfBigDecimals": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-float-special-values.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-float-special-values.json new file mode 100644 index 0000000000..1eac52f24b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-float-special-values.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {id: {_in: [\"scalar-special-float\", \"scalar-neg-inf\", \"scalar-extremes\"]}}, order_by: {id: asc}) { id float_ optFloat } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-extremes", + "float_": "1.7976931348623157e+308", + "optFloat": "5e-324" + }, + { + "id": "scalar-neg-inf", + "float_": "-Infinity", + "optFloat": "-0" + }, + { + "id": "scalar-special-float", + "float_": "Infinity", + "optFloat": "NaN" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-contained-in.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-contained-in.json new file mode 100644 index 0000000000..ad47d9167b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-contained-in.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {json: {_contained_in: {kind: \"object\", n: 1, nested: {a: [1, 2]}, extra: true}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1" + }, + { + "id": "all-empty-arrays" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-contains.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-contains.json new file mode 100644 index 0000000000..5fd0bb63bd --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-contains.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {json: {_contains: {kind: \"object\"}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-has-key.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-has-key.json new file mode 100644 index 0000000000..3f39697e2a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-has-key.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {json: {_has_key: \"nested\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-has-keys-all.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-has-keys-all.json new file mode 100644 index 0000000000..b1a6cba55e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-has-keys-all.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {json: {_has_keys_all: [\"kind\", \"n\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-has-keys-any.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-has-keys-any.json new file mode 100644 index 0000000000..9418d038c2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-has-keys-any.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {json: {_has_keys_any: [\"kind\", \"héllo\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1" + }, + { + "id": "all-json-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-path-arg.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-path-arg.json new file mode 100644 index 0000000000..5b31600951 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-path-arg.json @@ -0,0 +1,20 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {id: {_eq: \"all-1\"}}) { id json(path: \"$.nested.a\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1", + "json": [ + 1, + 2 + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-path-index.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-path-index.json new file mode 100644 index 0000000000..fecad3ff87 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-path-index.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {id: {_eq: \"all-array-edge\"}}) { id json(path: \"$[4].k\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-array-edge", + "json": "v" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-path-missing.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-path-missing.json new file mode 100644 index 0000000000..1140ed93bb --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-path-missing.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {id: {_eq: \"all-1\"}}) { id json(path: \"$.does.not.exist\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1", + "json": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-variants.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-variants.json new file mode 100644 index 0000000000..3870a94f29 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-jsonb-variants.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {id: {_like: \"all-json%\"}}, order_by: {id: asc}) { id json } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-json-bool", + "json": false + }, + { + "id": "all-json-null", + "json": null + }, + { + "id": "all-json-number", + "json": 1.2345678901234568e+29 + }, + { + "id": "all-json-string", + "json": "just a string" + }, + { + "id": "all-json-unicode", + "json": { + "esc": "a\"b\\c\nd", + "num": 1e+100, + "héllo": "wörld 🚀" + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-numeric-array-precision.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-numeric-array-precision.json new file mode 100644 index 0000000000..2aa5e8d2ce --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-numeric-array-precision.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ PostgresNumericPrecisionEntityTester(where: {id: {_eq: \"prec-1\"}}) { id exampleBigIntArray exampleBigDecimalArray } }" + }, + "status": 200, + "body": { + "data": { + "PostgresNumericPrecisionEntityTester": [ + { + "id": "prec-1", + "exampleBigIntArray": [ + 1, + 2, + 3 + ], + "exampleBigDecimalArray": [ + 0.00001, + -0.00001 + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-numeric-precision-monsters.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-numeric-precision-monsters.json new file mode 100644 index 0000000000..5dd389d6d0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-numeric-precision-monsters.json @@ -0,0 +1,70 @@ +{ + "role": "public", + "request": { + "query": "{ PostgresNumericPrecisionEntityTester(order_by: {id: asc}) { id exampleBigInt exampleBigIntRequired exampleBigIntArray exampleBigIntArrayRequired exampleBigDecimal exampleBigDecimalRequired exampleBigDecimalArray exampleBigDecimalArrayRequired exampleBigDecimalOtherOrder } }" + }, + "status": 200, + "body": { + "data": { + "PostgresNumericPrecisionEntityTester": [ + { + "id": "prec-1", + "exampleBigInt": "9999999999999999999999999999999999999999999999999999999999999999999999999999", + "exampleBigIntRequired": "99999999999999999999999999999999999999999999999999999999999999999999999999999", + "exampleBigIntArray": [ + 1, + 2, + 3 + ], + "exampleBigIntArrayRequired": [ + -1, + -2, + -3 + ], + "exampleBigDecimal": "123456789012345678901234567890123456789012345678901234567890123456789012345.12345", + "exampleBigDecimalRequired": "-123456789012345678901234567890123456789012345678901234567890123456789012345.54321", + "exampleBigDecimalArray": [ + 0.00001, + -0.00001 + ], + "exampleBigDecimalArrayRequired": [ + 123.45678 + ], + "exampleBigDecimalOtherOrder": "0.123456" + }, + { + "id": "prec-2", + "exampleBigInt": "-1", + "exampleBigIntRequired": "1", + "exampleBigIntArray": [ + 0 + ], + "exampleBigIntArrayRequired": [ + 9999999999 + ], + "exampleBigDecimal": "1.50000", + "exampleBigDecimalRequired": "-1.50000", + "exampleBigDecimalArray": [ + 1.1 + ], + "exampleBigDecimalArrayRequired": [ + -1.1 + ], + "exampleBigDecimalOtherOrder": "-0.000001" + }, + { + "id": "prec-nulls", + "exampleBigInt": null, + "exampleBigIntRequired": "0", + "exampleBigIntArray": null, + "exampleBigIntArrayRequired": [], + "exampleBigDecimal": null, + "exampleBigDecimalRequired": "0.00000", + "exampleBigDecimalArray": null, + "exampleBigDecimalArrayRequired": [], + "exampleBigDecimalOtherOrder": "0.000000" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-string-arrays-escaping.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-string-arrays-escaping.json new file mode 100644 index 0000000000..6ebe9d9eaa --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-string-arrays-escaping.json @@ -0,0 +1,26 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {id: {_eq: \"all-array-edge\"}}) { id arrayOfStrings } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-array-edge", + "arrayOfStrings": [ + "with,comma", + "with}brace", + "with\"quote", + "with'single", + "", + " leading space", + "emoji 🚀", + "back\\slash" + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-timestamp-precision.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-timestamp-precision.json new file mode 100644 index 0000000000..351f14b9b2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-timestamp-precision.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp(order_by: {id: asc}) { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp": [ + { + "id": "ts-epoch", + "timestamp": "1970-01-01T00:00:00+00:00" + }, + { + "id": "ts-future", + "timestamp": "9999-12-31T23:59:59.999999+00:00" + }, + { + "id": "ts-micro", + "timestamp": "2024-01-15T12:34:56.123456+00:00" + }, + { + "id": "ts-milli", + "timestamp": "2024-01-15T12:34:56.123+00:00" + }, + { + "id": "ts-pre-epoch", + "timestamp": "1969-07-20T20:17:40+00:00" + }, + { + "id": "ts-zoned", + "timestamp": "2024-06-15T02:30:00+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-unicode-strings.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-unicode-strings.json new file mode 100644 index 0000000000..345f254596 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-unicode-strings.json @@ -0,0 +1,23 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {id: {_in: [\"scalar-unicode\", \"scalar-quotes\"]}}, order_by: {id: asc}) { id string optString } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-quotes", + "string": "with \"double\" and 'single' and back\\slash and\nnewline and\ttab", + "optString": "end" + }, + { + "id": "scalar-unicode", + "string": "héllo wörld 中文测试 🚀🎉", + "optString": "emoji 🤖" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-where-on-array-column-eq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-where-on-array-column-eq.json new file mode 100644 index 0000000000..098475f148 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/scalars-where-on-array-column-eq.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {arrayOfStrings: {_eq: [\"one\", \"two\", \"three\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-arrays-alltypes-string-vs-number.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-arrays-alltypes-string-vs-number.json new file mode 100644 index 0000000000..a86f0e1c61 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-arrays-alltypes-string-vs-number.json @@ -0,0 +1,163 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(order_by: {id: asc}) { id arrayOfInts float_ arrayOfFloats bigInt arrayOfBigInts bigDecimal arrayOfBigDecimals } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1", + "arrayOfInts": [ + 1, + 2, + 3 + ], + "float_": "1.5", + "arrayOfFloats": [ + 1.5, + 2.5, + -3.5 + ], + "bigInt": "1000", + "arrayOfBigInts": [ + "1", + "2", + "3" + ], + "bigDecimal": "10.5", + "arrayOfBigDecimals": [ + "1.5", + "2.25" + ] + }, + { + "id": "all-array-edge", + "arrayOfInts": [ + -2147483648, + 0, + 2147483647 + ], + "float_": "-1.5", + "arrayOfFloats": [ + 0, + -0.5 + ], + "bigInt": "-1", + "arrayOfBigInts": [ + "-99999999999999999999999999999999999999", + "0", + "99999999999999999999999999999999999999" + ], + "bigDecimal": "-0.5", + "arrayOfBigDecimals": [ + "-1.5", + "0.0", + "1.500" + ] + }, + { + "id": "all-empty-arrays", + "arrayOfInts": [], + "float_": "0", + "arrayOfFloats": [], + "bigInt": "0", + "arrayOfBigInts": [], + "bigDecimal": "0", + "arrayOfBigDecimals": [] + }, + { + "id": "all-json-bool", + "arrayOfInts": [ + 9 + ], + "float_": "9.5", + "arrayOfFloats": [ + 9.5 + ], + "bigInt": "9", + "arrayOfBigInts": [ + "9" + ], + "bigDecimal": "9.5", + "arrayOfBigDecimals": [ + "9.5" + ] + }, + { + "id": "all-json-null", + "arrayOfInts": [ + 7 + ], + "float_": "7.5", + "arrayOfFloats": [ + 7.5 + ], + "bigInt": "7", + "arrayOfBigInts": [ + "7" + ], + "bigDecimal": "7.5", + "arrayOfBigDecimals": [ + "7.5" + ] + }, + { + "id": "all-json-number", + "arrayOfInts": [ + 6 + ], + "float_": "6.5", + "arrayOfFloats": [ + 6.5 + ], + "bigInt": "6", + "arrayOfBigInts": [ + "6" + ], + "bigDecimal": "6.5", + "arrayOfBigDecimals": [ + "6.5" + ] + }, + { + "id": "all-json-string", + "arrayOfInts": [ + 5 + ], + "float_": "5.5", + "arrayOfFloats": [ + 5.5 + ], + "bigInt": "5", + "arrayOfBigInts": [ + "5" + ], + "bigDecimal": "5.5", + "arrayOfBigDecimals": [ + "5.5" + ] + }, + { + "id": "all-json-unicode", + "arrayOfInts": [ + 8 + ], + "float_": "8.5", + "arrayOfFloats": [ + 8.5 + ], + "bigInt": "8", + "arrayOfBigInts": [ + "8" + ], + "bigDecimal": "8.5", + "arrayOfBigDecimals": [ + "8.5" + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-arrays-numeric-precision-string-vs-number.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-arrays-numeric-precision-string-vs-number.json new file mode 100644 index 0000000000..89e2461397 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-arrays-numeric-precision-string-vs-number.json @@ -0,0 +1,61 @@ +{ + "role": "public", + "request": { + "query": "{ PostgresNumericPrecisionEntityTester(order_by: {id: asc}) { id exampleBigInt exampleBigIntArray exampleBigIntArrayRequired exampleBigDecimal exampleBigDecimalArray exampleBigDecimalArrayRequired } }" + }, + "status": 200, + "body": { + "data": { + "PostgresNumericPrecisionEntityTester": [ + { + "id": "prec-1", + "exampleBigInt": "9999999999999999999999999999999999999999999999999999999999999999999999999999", + "exampleBigIntArray": [ + 1, + 2, + 3 + ], + "exampleBigIntArrayRequired": [ + -1, + -2, + -3 + ], + "exampleBigDecimal": "123456789012345678901234567890123456789012345678901234567890123456789012345.12345", + "exampleBigDecimalArray": [ + 0.00001, + -0.00001 + ], + "exampleBigDecimalArrayRequired": [ + 123.45678 + ] + }, + { + "id": "prec-2", + "exampleBigInt": "-1", + "exampleBigIntArray": [ + 0 + ], + "exampleBigIntArrayRequired": [ + 9999999999 + ], + "exampleBigDecimal": "1.50000", + "exampleBigDecimalArray": [ + 1.1 + ], + "exampleBigDecimalArrayRequired": [ + -1.1 + ] + }, + { + "id": "prec-nulls", + "exampleBigInt": null, + "exampleBigIntArray": null, + "exampleBigIntArrayRequired": [], + "exampleBigDecimal": null, + "exampleBigDecimalArray": null, + "exampleBigDecimalArrayRequired": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-bypk-special-chars-full.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-bypk-special-chars-full.json new file mode 100644 index 0000000000..406af210b6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-bypk-special-chars-full.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ User_by_pk(id: \"user \\\"quoted\\\" 🚀\") { id address gravatar_id updatesCountOnUserForTesting accountType } }" + }, + "status": 200, + "body": { + "data": { + "User_by_pk": { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005", + "gravatar_id": null, + "updatesCountOnUserForTesting": 5, + "accountType": "USER" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-bypk-special-chars-variable.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-bypk-special-chars-variable.json new file mode 100644 index 0000000000..ee935357b8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-bypk-special-chars-variable.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "query ($id: String!) { User_by_pk(id: $id) { id address accountType } }", + "variables": { + "id": "user \"quoted\" 🚀" + } + }, + "status": 200, + "body": { + "data": { + "User_by_pk": { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005", + "accountType": "USER" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-field-order-interleaved.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-field-order-interleaved.json new file mode 100644 index 0000000000..97d30b2e0a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-field-order-interleaved.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-1\") { json bool __typename bigDecimal id enumField arrayOfInts } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "json": { + "n": 1, + "kind": "object", + "nested": { + "a": [ + 1, + 2 + ] + } + }, + "bool": true, + "__typename": "EntityWithAllTypes", + "bigDecimal": "10.5", + "id": "all-1", + "enumField": "ADMIN", + "arrayOfInts": [ + 1, + 2, + 3 + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-field-order-reverse-schema.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-field-order-reverse-schema.json new file mode 100644 index 0000000000..ac711d6980 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-field-order-reverse-schema.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes_by_pk(id: \"scalar-1\") { optTimestamp timestamp optEnumField enumField bigDecimalWithConfig optBigDecimal bigDecimal optBigInt bigInt optBool bool optFloat float_ optInt int_ optString string id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_by_pk": { + "optTimestamp": "2024-01-15T12:34:56.789123+00:00", + "timestamp": "2024-01-15T12:34:56.789+00:00", + "optEnumField": "USER", + "enumField": "ADMIN", + "bigDecimalWithConfig": "1.00000001", + "optBigDecimal": "3.75", + "bigDecimal": "1.25", + "optBigInt": "200", + "bigInt": "100", + "optBool": true, + "bool": true, + "optFloat": "2.5", + "float_": "1.5", + "optInt": 10, + "int_": 1, + "optString": "present", + "string": "plain", + "id": "scalar-1" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-alias-three-paths.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-alias-three-paths.json new file mode 100644 index 0000000000..dd782591d1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-alias-three-paths.json @@ -0,0 +1,26 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-1\") { id whole: json(path: \"$\") kind: json(path: \"$.kind\") second: json(path: \"$.nested.a[0]\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-1", + "whole": { + "n": 1, + "kind": "object", + "nested": { + "a": [ + 1, + 2 + ] + } + }, + "kind": "object", + "second": 1 + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-dollar-root.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-dollar-root.json new file mode 100644 index 0000000000..67c6035351 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-dollar-root.json @@ -0,0 +1,24 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-1\") { id json(path: \"$\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-1", + "json": { + "n": 1, + "kind": "object", + "nested": { + "a": [ + 1, + 2 + ] + } + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-empty-string-error.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-empty-string-error.json new file mode 100644 index 0000000000..8ada3ff485 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-empty-string-error.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-1\") { id json(path: \"\") } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "parse json path error: . Accept letters, digits, underscore (_) or hyphen (-) only. Use quotes enclosed in bracket ([\"...\"]) if there is any special character", + "extensions": { + "path": "$.selectionSet.EntityWithAllTypes_by_pk.selectionSet.json.args", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-key.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-key.json new file mode 100644 index 0000000000..d0f54f9d82 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-key.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-1\") { id json(path: \"$.kind\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-1", + "json": "object" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-missing-nested.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-missing-nested.json new file mode 100644 index 0000000000..9efb27f38b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-missing-nested.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-1\") { id json(path: \"$.nested.missing.deep\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-1", + "json": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-nested-index.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-nested-index.json new file mode 100644 index 0000000000..c7b983df36 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-nested-index.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-1\") { id json(path: \"$.nested.a[1]\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-1", + "json": 2 + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-no-dollar-prefix.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-no-dollar-prefix.json new file mode 100644 index 0000000000..a33ba0b80d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-no-dollar-prefix.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-1\") { id json(path: \"kind\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-1", + "json": "object" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-on-json-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-on-json-null.json new file mode 100644 index 0000000000..bf5dc38117 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-on-json-null.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-json-null\") { id json(path: \"$.x\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-json-null", + "json": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-on-scalar-value.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-on-scalar-value.json new file mode 100644 index 0000000000..dd191fcc7d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-on-scalar-value.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-json-string\") { id json(path: \"$.anything\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-json-string", + "json": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-root-index.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-root-index.json new file mode 100644 index 0000000000..f6917d2b04 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-root-index.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-array-edge\") { id json(path: \"$[0]\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-array-edge", + "json": 1 + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-unicode-key.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-unicode-key.json new file mode 100644 index 0000000000..c28885f072 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-unicode-key.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-json-unicode\") { id json(path: \"$.héllo\") } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-json-unicode", + "json": "wörld 🚀" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-variable.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-variable.json new file mode 100644 index 0000000000..88029bd1a2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-json-path-variable.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($p: String) { EntityWithAllTypes_by_pk(id: \"all-1\") { id json(path: $p) } }", + "variables": { + "p": "$.nested.a" + } + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-1", + "json": [ + 1, + 2 + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-1.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-1.json new file mode 100644 index 0000000000..7e4547a3b7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-1.json @@ -0,0 +1,65 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-1\") { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-1", + "string": "first", + "optString": "opt", + "arrayOfStrings": [ + "one", + "two", + "three" + ], + "int_": 1, + "optInt": 2, + "arrayOfInts": [ + 1, + 2, + 3 + ], + "float_": "1.5", + "optFloat": "2.5", + "arrayOfFloats": [ + 1.5, + 2.5, + -3.5 + ], + "bool": true, + "optBool": false, + "bigInt": "1000", + "optBigInt": "2000", + "arrayOfBigInts": [ + "1", + "2", + "3" + ], + "bigDecimal": "10.5", + "optBigDecimal": "20.5", + "bigDecimalWithConfig": "1.12345678", + "arrayOfBigDecimals": [ + "1.5", + "2.25" + ], + "timestamp": "2024-01-01T00:00:00+00:00", + "optTimestamp": "2024-01-02T00:00:00+00:00", + "json": { + "n": 1, + "kind": "object", + "nested": { + "a": [ + 1, + 2 + ] + } + }, + "enumField": "ADMIN", + "optEnumField": "USER" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-array-edge.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-array-edge.json new file mode 100644 index 0000000000..ffa80ee8ce --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-array-edge.json @@ -0,0 +1,72 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-array-edge\") { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-array-edge", + "string": "array edges", + "optString": "x", + "arrayOfStrings": [ + "with,comma", + "with}brace", + "with\"quote", + "with'single", + "", + " leading space", + "emoji 🚀", + "back\\slash" + ], + "int_": -1, + "optInt": -2, + "arrayOfInts": [ + -2147483648, + 0, + 2147483647 + ], + "float_": "-1.5", + "optFloat": null, + "arrayOfFloats": [ + 0, + -0.5 + ], + "bool": true, + "optBool": true, + "bigInt": "-1", + "optBigInt": "1", + "arrayOfBigInts": [ + "-99999999999999999999999999999999999999", + "0", + "99999999999999999999999999999999999999" + ], + "bigDecimal": "-0.5", + "optBigDecimal": "0.5", + "bigDecimalWithConfig": "-1.00000001", + "arrayOfBigDecimals": [ + "-1.5", + "0.0", + "1.500" + ], + "timestamp": "2024-05-05T05:05:05.55555+00:00", + "optTimestamp": "2024-05-05T05:05:05.555555+00:00", + "json": [ + 1, + "two", + null, + true, + { + "k": "v" + }, + [ + 2.5 + ] + ], + "enumField": "ADMIN", + "optEnumField": "ADMIN" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-empty-arrays.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-empty-arrays.json new file mode 100644 index 0000000000..5a73420a4c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-empty-arrays.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-empty-arrays\") { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-empty-arrays", + "string": "empty", + "optString": null, + "arrayOfStrings": [], + "int_": 0, + "optInt": null, + "arrayOfInts": [], + "float_": "0", + "optFloat": null, + "arrayOfFloats": [], + "bool": false, + "optBool": null, + "bigInt": "0", + "optBigInt": null, + "arrayOfBigInts": [], + "bigDecimal": "0", + "optBigDecimal": null, + "bigDecimalWithConfig": "0.00000000", + "arrayOfBigDecimals": [], + "timestamp": "2024-01-01T00:00:00+00:00", + "optTimestamp": null, + "json": {}, + "enumField": "USER", + "optEnumField": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-bool.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-bool.json new file mode 100644 index 0000000000..0868fc5ecc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-bool.json @@ -0,0 +1,47 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-json-bool\") { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-json-bool", + "string": "json scalar bool", + "optString": null, + "arrayOfStrings": [ + "e" + ], + "int_": 9, + "optInt": null, + "arrayOfInts": [ + 9 + ], + "float_": "9.5", + "optFloat": null, + "arrayOfFloats": [ + 9.5 + ], + "bool": true, + "optBool": null, + "bigInt": "9", + "optBigInt": null, + "arrayOfBigInts": [ + "9" + ], + "bigDecimal": "9.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "9.00000000", + "arrayOfBigDecimals": [ + "9.5" + ], + "timestamp": "2024-02-06T02:02:02+00:00", + "optTimestamp": null, + "json": false, + "enumField": "USER", + "optEnumField": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-null.json new file mode 100644 index 0000000000..2323a5f2d2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-null.json @@ -0,0 +1,47 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-json-null\") { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-json-null", + "string": "jsonb null literal", + "optString": null, + "arrayOfStrings": [ + "c" + ], + "int_": 7, + "optInt": null, + "arrayOfInts": [ + 7 + ], + "float_": "7.5", + "optFloat": null, + "arrayOfFloats": [ + 7.5 + ], + "bool": true, + "optBool": null, + "bigInt": "7", + "optBigInt": null, + "arrayOfBigInts": [ + "7" + ], + "bigDecimal": "7.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "7.00000000", + "arrayOfBigDecimals": [ + "7.5" + ], + "timestamp": "2024-02-04T02:02:02+00:00", + "optTimestamp": null, + "json": null, + "enumField": "ADMIN", + "optEnumField": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-number.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-number.json new file mode 100644 index 0000000000..24f8ce77d3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-number.json @@ -0,0 +1,47 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-json-number\") { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-json-number", + "string": "json scalar number", + "optString": null, + "arrayOfStrings": [ + "b" + ], + "int_": 6, + "optInt": null, + "arrayOfInts": [ + 6 + ], + "float_": "6.5", + "optFloat": null, + "arrayOfFloats": [ + 6.5 + ], + "bool": false, + "optBool": null, + "bigInt": "6", + "optBigInt": null, + "arrayOfBigInts": [ + "6" + ], + "bigDecimal": "6.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "6.00000000", + "arrayOfBigDecimals": [ + "6.5" + ], + "timestamp": "2024-02-03T02:02:02+00:00", + "optTimestamp": null, + "json": 1.2345678901234568e+29, + "enumField": "USER", + "optEnumField": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-string.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-string.json new file mode 100644 index 0000000000..1655116465 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-string.json @@ -0,0 +1,47 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-json-string\") { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-json-string", + "string": "json scalar string", + "optString": null, + "arrayOfStrings": [ + "a" + ], + "int_": 5, + "optInt": 5, + "arrayOfInts": [ + 5 + ], + "float_": "5.5", + "optFloat": "5.5", + "arrayOfFloats": [ + 5.5 + ], + "bool": true, + "optBool": null, + "bigInt": "5", + "optBigInt": "5", + "arrayOfBigInts": [ + "5" + ], + "bigDecimal": "5.5", + "optBigDecimal": "5.5", + "bigDecimalWithConfig": "5.00000000", + "arrayOfBigDecimals": [ + "5.5" + ], + "timestamp": "2024-02-02T02:02:02+00:00", + "optTimestamp": null, + "json": "just a string", + "enumField": "USER", + "optEnumField": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-unicode.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-unicode.json new file mode 100644 index 0000000000..b9ac367847 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-alltypes-all-json-unicode.json @@ -0,0 +1,51 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes_by_pk(id: \"all-json-unicode\") { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes_by_pk": { + "id": "all-json-unicode", + "string": "json unicode", + "optString": null, + "arrayOfStrings": [ + "d" + ], + "int_": 8, + "optInt": null, + "arrayOfInts": [ + 8 + ], + "float_": "8.5", + "optFloat": null, + "arrayOfFloats": [ + 8.5 + ], + "bool": false, + "optBool": null, + "bigInt": "8", + "optBigInt": null, + "arrayOfBigInts": [ + "8" + ], + "bigDecimal": "8.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "8.00000000", + "arrayOfBigDecimals": [ + "8.5" + ], + "timestamp": "2024-02-05T02:02:02+00:00", + "optTimestamp": null, + "json": { + "esc": "a\"b\\c\nd", + "num": 1e+100, + "héllo": "wörld 🚀" + }, + "enumField": "USER", + "optEnumField": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-1.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-1.json new file mode 100644 index 0000000000..dacc5ebc6d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-1.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithBigDecimal_by_pk(id: \"bd-1\") { id bigDecimal } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithBigDecimal_by_pk": { + "id": "bd-1", + "bigDecimal": "0" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-2.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-2.json new file mode 100644 index 0000000000..e6ad76a046 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-2.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithBigDecimal_by_pk(id: \"bd-2\") { id bigDecimal } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithBigDecimal_by_pk": { + "id": "bd-2", + "bigDecimal": "1.10" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-3.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-3.json new file mode 100644 index 0000000000..36181e1a09 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-3.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithBigDecimal_by_pk(id: \"bd-3\") { id bigDecimal } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithBigDecimal_by_pk": { + "id": "bd-3", + "bigDecimal": "-1.10" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-4.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-4.json new file mode 100644 index 0000000000..cfe63c179b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-4.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithBigDecimal_by_pk(id: \"bd-4\") { id bigDecimal } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithBigDecimal_by_pk": { + "id": "bd-4", + "bigDecimal": "123456789.123456789" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-5.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-5.json new file mode 100644 index 0000000000..643b79cd55 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-bigdecimal-bd-5.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithBigDecimal_by_pk(id: \"bd-5\") { id bigDecimal } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithBigDecimal_by_pk": { + "id": "bd-5", + "bigDecimal": "0.000000000000000001" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-1.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-1.json new file mode 100644 index 0000000000..a69e5f35e7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-1.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes_by_pk(id: \"scalar-1\") { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_by_pk": { + "id": "scalar-1", + "string": "plain", + "optString": "present", + "int_": 1, + "optInt": 10, + "float_": "1.5", + "optFloat": "2.5", + "bool": true, + "optBool": true, + "bigInt": "100", + "optBigInt": "200", + "bigDecimal": "1.25", + "optBigDecimal": "3.75", + "bigDecimalWithConfig": "1.00000001", + "enumField": "ADMIN", + "optEnumField": "USER", + "timestamp": "2024-01-15T12:34:56.789+00:00", + "optTimestamp": "2024-01-15T12:34:56.789123+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-empty.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-empty.json new file mode 100644 index 0000000000..4dba951f8f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-empty.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes_by_pk(id: \"scalar-empty\") { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_by_pk": { + "id": "scalar-empty", + "string": "", + "optString": "", + "int_": 4, + "optInt": 0, + "float_": "-0.5", + "optFloat": "0", + "bool": true, + "optBool": false, + "bigInt": "10", + "optBigInt": "0", + "bigDecimal": "100", + "optBigDecimal": "0", + "bigDecimalWithConfig": "0.00000001", + "enumField": "USER", + "optEnumField": "ADMIN", + "timestamp": "2024-07-04T00:00:00.1+00:00", + "optTimestamp": "2024-07-04T00:00:00.12+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-extremes.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-extremes.json new file mode 100644 index 0000000000..bc4a7febb7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-extremes.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes_by_pk(id: \"scalar-extremes\") { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_by_pk": { + "id": "scalar-extremes", + "string": "extremes", + "optString": "x", + "int_": 2147483647, + "optInt": -2147483648, + "float_": "1.7976931348623157e+308", + "optFloat": "5e-324", + "bool": true, + "optBool": false, + "bigInt": "9999999999999999999999999999999999999999999999999999999999999999999999999999", + "optBigInt": "-9999999999999999999999999999999999999999999999999999999999999999999999999999", + "bigDecimal": "12345678901234567890.123456789", + "optBigDecimal": "-0.000000001", + "bigDecimalWithConfig": "99.99999999", + "enumField": "ADMIN", + "optEnumField": "ADMIN", + "timestamp": "9999-12-31T23:59:59.999999+00:00", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-neg-inf.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-neg-inf.json new file mode 100644 index 0000000000..8a72037ce9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-neg-inf.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes_by_pk(id: \"scalar-neg-inf\") { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_by_pk": { + "id": "scalar-neg-inf", + "string": "neg inf", + "optString": null, + "int_": -2, + "optInt": null, + "float_": "-Infinity", + "optFloat": "-0", + "bool": true, + "optBool": null, + "bigInt": "-1", + "optBigInt": null, + "bigDecimal": "-1.5", + "optBigDecimal": null, + "bigDecimalWithConfig": "-0.00000001", + "enumField": "USER", + "optEnumField": null, + "timestamp": "2024-07-01T00:00:00+00:00", + "optTimestamp": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-nulls.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-nulls.json new file mode 100644 index 0000000000..6c0d6d8090 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-nulls.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes_by_pk(id: \"scalar-nulls\") { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_by_pk": { + "id": "scalar-nulls", + "string": "has nulls", + "optString": null, + "int_": 0, + "optInt": null, + "float_": "0", + "optFloat": null, + "bool": false, + "optBool": null, + "bigInt": "0", + "optBigInt": null, + "bigDecimal": "0", + "optBigDecimal": null, + "bigDecimalWithConfig": "0.00000000", + "enumField": "USER", + "optEnumField": null, + "timestamp": "1970-01-01T00:00:00+00:00", + "optTimestamp": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-quotes.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-quotes.json new file mode 100644 index 0000000000..6c05663202 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-quotes.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes_by_pk(id: \"scalar-quotes\") { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_by_pk": { + "id": "scalar-quotes", + "string": "with \"double\" and 'single' and back\\slash and\nnewline and\ttab", + "optString": "end", + "int_": 3, + "optInt": 3, + "float_": "0.1", + "optFloat": "0.2", + "bool": false, + "optBool": false, + "bigInt": "7", + "optBigInt": "8", + "bigDecimal": "0.5", + "optBigDecimal": "0.5", + "bigDecimalWithConfig": "3.00000000", + "enumField": "ADMIN", + "optEnumField": "USER", + "timestamp": "2024-03-10T10:00:00+00:00", + "optTimestamp": "2024-03-10T10:00:00+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-special-float.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-special-float.json new file mode 100644 index 0000000000..57577c28c9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-special-float.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes_by_pk(id: \"scalar-special-float\") { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_by_pk": { + "id": "scalar-special-float", + "string": "inf and nan", + "optString": null, + "int_": -1, + "optInt": null, + "float_": "Infinity", + "optFloat": "NaN", + "bool": false, + "optBool": null, + "bigInt": "1", + "optBigInt": null, + "bigDecimal": "1.1000", + "optBigDecimal": null, + "bigDecimalWithConfig": "0.50000000", + "enumField": "USER", + "optEnumField": null, + "timestamp": "2000-02-29T00:00:00+00:00", + "optTimestamp": null + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-unicode.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-unicode.json new file mode 100644 index 0000000000..a3b1ee2bf4 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-nonarray-scalar-unicode.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes_by_pk(id: \"scalar-unicode\") { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes_by_pk": { + "id": "scalar-unicode", + "string": "héllo wörld 中文测试 🚀🎉", + "optString": "emoji 🤖", + "int_": 7, + "optInt": 7, + "float_": "-3.14159", + "optFloat": "2.718281828459045", + "bool": true, + "optBool": true, + "bigInt": "42", + "optBigInt": "-42", + "bigDecimal": "3.14000", + "optBigDecimal": "0.00000", + "bigDecimalWithConfig": "2.50000000", + "enumField": "USER", + "optEnumField": "USER", + "timestamp": "2024-12-25T13:00:00+00:00", + "optTimestamp": "2024-12-26T02:30:00+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-precision-prec-1.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-precision-prec-1.json new file mode 100644 index 0000000000..1aba476f2d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-precision-prec-1.json @@ -0,0 +1,36 @@ +{ + "role": "public", + "request": { + "query": "{ PostgresNumericPrecisionEntityTester_by_pk(id: \"prec-1\") { id exampleBigInt exampleBigIntRequired exampleBigIntArray exampleBigIntArrayRequired exampleBigDecimal exampleBigDecimalRequired exampleBigDecimalArray exampleBigDecimalArrayRequired exampleBigDecimalOtherOrder } }" + }, + "status": 200, + "body": { + "data": { + "PostgresNumericPrecisionEntityTester_by_pk": { + "id": "prec-1", + "exampleBigInt": "9999999999999999999999999999999999999999999999999999999999999999999999999999", + "exampleBigIntRequired": "99999999999999999999999999999999999999999999999999999999999999999999999999999", + "exampleBigIntArray": [ + 1, + 2, + 3 + ], + "exampleBigIntArrayRequired": [ + -1, + -2, + -3 + ], + "exampleBigDecimal": "123456789012345678901234567890123456789012345678901234567890123456789012345.12345", + "exampleBigDecimalRequired": "-123456789012345678901234567890123456789012345678901234567890123456789012345.54321", + "exampleBigDecimalArray": [ + 0.00001, + -0.00001 + ], + "exampleBigDecimalArrayRequired": [ + 123.45678 + ], + "exampleBigDecimalOtherOrder": "0.123456" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-precision-prec-2.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-precision-prec-2.json new file mode 100644 index 0000000000..8aa2524702 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-precision-prec-2.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ PostgresNumericPrecisionEntityTester_by_pk(id: \"prec-2\") { id exampleBigInt exampleBigIntRequired exampleBigIntArray exampleBigIntArrayRequired exampleBigDecimal exampleBigDecimalRequired exampleBigDecimalArray exampleBigDecimalArrayRequired exampleBigDecimalOtherOrder } }" + }, + "status": 200, + "body": { + "data": { + "PostgresNumericPrecisionEntityTester_by_pk": { + "id": "prec-2", + "exampleBigInt": "-1", + "exampleBigIntRequired": "1", + "exampleBigIntArray": [ + 0 + ], + "exampleBigIntArrayRequired": [ + 9999999999 + ], + "exampleBigDecimal": "1.50000", + "exampleBigDecimalRequired": "-1.50000", + "exampleBigDecimalArray": [ + 1.1 + ], + "exampleBigDecimalArrayRequired": [ + -1.1 + ], + "exampleBigDecimalOtherOrder": "-0.000001" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-precision-prec-nulls.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-precision-prec-nulls.json new file mode 100644 index 0000000000..7d61f9c2c6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-precision-prec-nulls.json @@ -0,0 +1,23 @@ +{ + "role": "public", + "request": { + "query": "{ PostgresNumericPrecisionEntityTester_by_pk(id: \"prec-nulls\") { id exampleBigInt exampleBigIntRequired exampleBigIntArray exampleBigIntArrayRequired exampleBigDecimal exampleBigDecimalRequired exampleBigDecimalArray exampleBigDecimalArrayRequired exampleBigDecimalOtherOrder } }" + }, + "status": 200, + "body": { + "data": { + "PostgresNumericPrecisionEntityTester_by_pk": { + "id": "prec-nulls", + "exampleBigInt": null, + "exampleBigIntRequired": "0", + "exampleBigIntArray": null, + "exampleBigIntArrayRequired": [], + "exampleBigDecimal": null, + "exampleBigDecimalRequired": "0.00000", + "exampleBigDecimalArray": null, + "exampleBigDecimalArrayRequired": [], + "exampleBigDecimalOtherOrder": "0.000000" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-epoch.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-epoch.json new file mode 100644 index 0000000000..f60ff0ae71 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-epoch.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp_by_pk(id: \"ts-epoch\") { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp_by_pk": { + "id": "ts-epoch", + "timestamp": "1970-01-01T00:00:00+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-future.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-future.json new file mode 100644 index 0000000000..dcefed4b63 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-future.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp_by_pk(id: \"ts-future\") { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp_by_pk": { + "id": "ts-future", + "timestamp": "9999-12-31T23:59:59.999999+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-micro.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-micro.json new file mode 100644 index 0000000000..d6fd76ee13 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-micro.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp_by_pk(id: \"ts-micro\") { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp_by_pk": { + "id": "ts-micro", + "timestamp": "2024-01-15T12:34:56.123456+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-milli.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-milli.json new file mode 100644 index 0000000000..d456288099 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-milli.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp_by_pk(id: \"ts-milli\") { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp_by_pk": { + "id": "ts-milli", + "timestamp": "2024-01-15T12:34:56.123+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-pre-epoch.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-pre-epoch.json new file mode 100644 index 0000000000..5a510b97ed --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-pre-epoch.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp_by_pk(id: \"ts-pre-epoch\") { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp_by_pk": { + "id": "ts-pre-epoch", + "timestamp": "1969-07-20T20:17:40+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-zoned.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-zoned.json new file mode 100644 index 0000000000..428b7849cc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-row-timestamp-ts-zoned.json @@ -0,0 +1,15 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp_by_pk(id: \"ts-zoned\") { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp_by_pk": { + "id": "ts-zoned", + "timestamp": "2024-06-15T02:30:00+00:00" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-typename-only-by-pk.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-typename-only-by-pk.json new file mode 100644 index 0000000000..379b55ee82 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-typename-only-by-pk.json @@ -0,0 +1,14 @@ +{ + "role": "public", + "request": { + "query": "{ PostgresNumericPrecisionEntityTester_by_pk(id: \"prec-1\") { __typename } }" + }, + "status": 200, + "body": { + "data": { + "PostgresNumericPrecisionEntityTester_by_pk": { + "__typename": "PostgresNumericPrecisionEntityTester" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/ss-typename-only-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-typename-only-list.json new file mode 100644 index 0000000000..b62b5f8c1b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/ss-typename-only-list.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithBigDecimal(order_by: {id: asc}) { __typename } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithBigDecimal": [ + { + "__typename": "EntityWithBigDecimal" + }, + { + "__typename": "EntityWithBigDecimal" + }, + { + "__typename": "EntityWithBigDecimal" + }, + { + "__typename": "EntityWithBigDecimal" + }, + { + "__typename": "EntityWithBigDecimal" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/variables-limit-offset-order.json b/packages/e2e-tests/fixtures/differential/snapshots/default/variables-limit-offset-order.json new file mode 100644 index 0000000000..115e16b409 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/variables-limit-offset-order.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "query ($l: Int, $o: Int, $ord: [SimpleEntity_order_by!]) { SimpleEntity(limit: $l, offset: $o, order_by: $ord) { id } }", + "variables": { + "l": 3, + "o": 1, + "ord": [ + { + "id": "desc" + } + ] + } + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-8" + }, + { + "id": "simple-7" + }, + { + "id": "simple-6" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-admin-mutation-insert-unknown-table.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-admin-mutation-insert-unknown-table.json new file mode 100644 index 0000000000..6ebea8a15d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-admin-mutation-insert-unknown-table.json @@ -0,0 +1,18 @@ +{ + "role": "admin", + "request": { + "query": "mutation { insert_Bogus(objects: []) { affected_rows } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'insert_Bogus' not found in type: 'mutation_root'", + "extensions": { + "path": "$.selectionSet.insert_Bogus", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-alias-duplicate-root-different-args.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-alias-duplicate-root-different-args.json new file mode 100644 index 0000000000..5b66bc40b5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-alias-duplicate-root-different-args.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ few: SimpleEntity(order_by: {id: asc}, limit: 2) { id } more: SimpleEntity(order_by: {id: desc}, limit: 3) { id value } one: SimpleEntity_by_pk(id: \"simple-5\") { id } miss: SimpleEntity_by_pk(id: \"nope\") { id } }" + }, + "status": 200, + "body": { + "data": { + "few": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + } + ], + "more": [ + { + "id": "simple-9", + "value": "v9" + }, + { + "id": "simple-8", + "value": "v8" + }, + { + "id": "simple-7", + "value": "v7" + } + ], + "one": { + "id": "simple-5" + }, + "miss": null + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-default-bool-exp-used.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-default-bool-exp-used.json new file mode 100644 index 0000000000..3864eb4788 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-default-bool-exp-used.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "query ($w: SimpleEntity_bool_exp = {id: {_eq: \"simple-2\"}}) { SimpleEntity(where: $w, order_by: {id: asc}) { id value } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-2", + "value": "v2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-default-int-overridden.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-default-int-overridden.json new file mode 100644 index 0000000000..ef2f7c170f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-default-int-overridden.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "query ($lim: Int = 2) { SimpleEntity(order_by: {id: asc}, limit: $lim) { id } }", + "variables": { + "lim": 1 + } + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-default-null-override.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-default-null-override.json new file mode 100644 index 0000000000..3a85e4a023 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-default-null-override.json @@ -0,0 +1,46 @@ +{ + "role": "public", + "request": { + "query": "query ($lim: Int = 2) { SimpleEntity(order_by: {id: asc}, limit: $lim) { id } }", + "variables": { + "lim": null + } + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-directive-include-fragment-spread-false.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-directive-include-fragment-spread-false.json new file mode 100644 index 0000000000..4c0e636389 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-directive-include-fragment-spread-false.json @@ -0,0 +1,22 @@ +{ + "role": "public", + "request": { + "query": "query ($inc: Boolean!) { User(order_by: {id: asc}, limit: 2) { id ...Extra @include(if: $inc) } } fragment Extra on User { address accountType }", + "variables": { + "inc": false + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-directive-include-fragment-spread.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-directive-include-fragment-spread.json new file mode 100644 index 0000000000..bec4947e93 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-directive-include-fragment-spread.json @@ -0,0 +1,26 @@ +{ + "role": "public", + "request": { + "query": "query ($inc: Boolean!) { User(order_by: {id: asc}, limit: 2) { id ...Extra @include(if: $inc) } } fragment Extra on User { address accountType }", + "variables": { + "inc": true + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "address": "0xaaaa000000000000000000000000000000000005", + "accountType": "USER" + }, + { + "id": "user-1", + "address": "0xaaaa000000000000000000000000000000000001", + "accountType": "ADMIN" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-directive-skip-inline-fragment.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-directive-skip-inline-fragment.json new file mode 100644 index 0000000000..a2cd17ff6d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-directive-skip-inline-fragment.json @@ -0,0 +1,22 @@ +{ + "role": "public", + "request": { + "query": "query ($skip: Boolean!) { User(order_by: {id: asc}, limit: 2) { id ... on User @skip(if: $skip) { address } } }", + "variables": { + "skip": true + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-boolean-string-in-include-directive.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-boolean-string-in-include-directive.json new file mode 100644 index 0000000000..a0d2f8d96c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-boolean-string-in-include-directive.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($b: Boolean!) { SimpleEntity(order_by: {id: asc}, limit: 1) { id value @include(if: $b) } }", + "variables": { + "b": "true" + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected a boolean for type 'Boolean', but found a string", + "extensions": { + "path": "$.selectionSet.SimpleEntity.selectionSet.include.args.if", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-directive-include-on-operation.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-directive-include-on-operation.json new file mode 100644 index 0000000000..a243d24bd2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-directive-include-on-operation.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "query Q @include(if: true) { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "directive 'include' is not allowed on a query", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-enum-scalar-invalid-value.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-enum-scalar-invalid-value.json new file mode 100644 index 0000000000..04113b772a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-enum-scalar-invalid-value.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($t: accounttype!) { User(where: {accountType: {_eq: $t}}, order_by: {id: asc}) { id } }", + "variables": { + "t": "SUPERADMIN" + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "invalid input value for enum accounttype: \"SUPERADMIN\"", + "extensions": { + "path": "$", + "code": "data-exception" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-extra-undeclared-variable.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-extra-undeclared-variable.json new file mode 100644 index 0000000000..b5fe878e2b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-extra-undeclared-variable.json @@ -0,0 +1,23 @@ +{ + "role": "public", + "request": { + "query": "query ($l: Int) { SimpleEntity(order_by: {id: asc}, limit: $l) { id } }", + "variables": { + "l": 2, + "extraneous": "ignored", + "another": 5 + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "unexpected variables in variableValues: extraneous, another", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-float8-variable-overflow.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-float8-variable-overflow.json new file mode 100644 index 0000000000..251fa27fc0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-float8-variable-overflow.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "query ($f: float8!) { EntityWithAllNonArrayTypes(where: {float_: {_lt: $f}}, order_by: {id: asc}) { id } }", + "rawVariables": "{\"f\":1e400}" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "The value 1.0e400 lies outside the bounds. Is it overflowing the float bounds?", + "extensions": { + "path": "$.selectionSet.EntityWithAllNonArrayTypes.args.where.float_._lt", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-id-type-variable.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-id-type-variable.json new file mode 100644 index 0000000000..45a1f1fd92 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-id-type-variable.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($id: ID!) { User_by_pk(id: $id) { id } }", + "variables": { + "id": "user-1" + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "variable 'id' is declared as 'ID!', but used where 'String!' is expected", + "extensions": { + "path": "$.selectionSet.User_by_pk.args.id", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-int-var-float-json.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-int-var-float-json.json new file mode 100644 index 0000000000..d65cd4642c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-int-var-float-json.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($l: Int!) { SimpleEntity(order_by: {id: asc}, limit: $l) { id } }", + "variables": { + "l": 1.5 + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "The value 1.5 lies outside the bounds or is not an integer. Maybe it is a float, or is there integer overflow?", + "extensions": { + "path": "$.selectionSet.SimpleEntity.args.limit", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-int-var-string-json.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-int-var-string-json.json new file mode 100644 index 0000000000..672f7675ae --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-int-var-string-json.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($l: Int!) { SimpleEntity(order_by: {id: asc}, limit: $l) { id } }", + "variables": { + "l": "1" + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "expected a non-negative 32-bit integer for type 'Int', but found a string", + "extensions": { + "path": "$.selectionSet.SimpleEntity.args.limit", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-numeric-var-bool.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-numeric-var-bool.json new file mode 100644 index 0000000000..bc9ffc63f2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-numeric-var-bool.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($n: numeric!) { Token(where: {tokenId: {_eq: $n}}, order_by: {id: asc}) { id } }", + "variables": { + "n": true + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "parsing Scientific failed, expected Number, but encountered Boolean", + "extensions": { + "path": "$.selectionSet.Token.args.where.tokenId._eq", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-opname-with-anonymous-op.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-opname-with-anonymous-op.json new file mode 100644 index 0000000000..006b695c70 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-opname-with-anonymous-op.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "query A { SimpleEntity(order_by: {id: asc}, limit: 1) { id } } { User(order_by: {id: asc}, limit: 1) { id } }", + "operationName": "A" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "operationName cannot be used when an anonymous operation exists in the document", + "extensions": { + "path": "$", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-same-alias-conflicting-args.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-same-alias-conflicting-args.json new file mode 100644 index 0000000000..b61ad5faab --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-same-alias-conflicting-args.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ x: SimpleEntity(order_by: {id: asc}, limit: 1) { id } x: SimpleEntity(order_by: {id: desc}, limit: 1) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "inconsistent arguments between multiple selections of field 'SimpleEntity'", + "extensions": { + "path": "$.selectionSet", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-string-list-int-element.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-string-list-int-element.json new file mode 100644 index 0000000000..6141069394 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-error-string-list-int-element.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($ids: [String!]!) { SimpleEntity(where: {id: {_in: $ids}}, order_by: {id: asc}) { id } }", + "variables": { + "ids": 5 + } + }, + "status": 200, + "body": { + "errors": [ + { + "message": "parsing Text failed, expected String, but encountered Number", + "extensions": { + "path": "$.selectionSet.SimpleEntity.args.where.id._in[0]", + "code": "parse-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-fragment-chain-deep.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-fragment-chain-deep.json new file mode 100644 index 0000000000..c3292c7e38 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-fragment-chain-deep.json @@ -0,0 +1,59 @@ +{ + "role": "public", + "request": { + "query": "fragment L1 on User { id ...L2 } fragment L2 on User { gravatar { ...L3 } } fragment L3 on Gravatar { id owner { ...L4 } } fragment L4 on User { address tokens(order_by: {id: asc}, limit: 1) { ...L5 } } fragment L5 on Token { id tokenId } { User(order_by: {id: asc}) { ...L1 } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "gravatar": null + }, + { + "id": "user-1", + "gravatar": { + "id": "grav-1", + "owner": { + "address": "0xaaaa000000000000000000000000000000000001", + "tokens": [ + { + "id": "tok-1", + "tokenId": "0" + } + ] + } + } + }, + { + "id": "user-2", + "gravatar": { + "id": "grav-2", + "owner": { + "address": "0xaaaa000000000000000000000000000000000002", + "tokens": [ + { + "id": "tok-3", + "tokenId": "2" + } + ] + } + } + }, + { + "id": "user-3", + "gravatar": null + }, + { + "id": "user-4", + "gravatar": null + }, + { + "id": "user-dangling", + "gravatar": null + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-opname-query-beside-mutation-public.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-opname-query-beside-mutation-public.json new file mode 100644 index 0000000000..bb3e6068d9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-opname-query-beside-mutation-public.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "query Q { SimpleEntity(order_by: {id: asc}, limit: 1) { id } } mutation M { insert_Bogus(objects: []) { affected_rows } }", + "operationName": "Q" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-opname-selects-op-with-vars.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-opname-selects-op-with-vars.json new file mode 100644 index 0000000000..f120fab3ca --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-opname-selects-op-with-vars.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query WithVar($v: String!) { SimpleEntity(where: {value: {_eq: $v}}, order_by: {id: asc}) { id value } } query NoVar { User(order_by: {id: asc}, limit: 1) { id } }", + "variables": { + "v": "v2" + }, + "operationName": "WithVar" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-2", + "value": "v2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-typename-aggregate-admin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-typename-aggregate-admin.json new file mode 100644 index 0000000000..b5991abc1e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-typename-aggregate-admin.json @@ -0,0 +1,64 @@ +{ + "role": "admin", + "request": { + "query": "{ Token_aggregate(order_by: {id: asc}) { __typename aggregate { __typename count sum { __typename tokenId } } nodes { __typename id } } }" + }, + "status": 200, + "body": { + "data": { + "Token_aggregate": { + "__typename": "Token_aggregate", + "aggregate": { + "__typename": "Token_aggregate_fields", + "count": 10, + "sum": { + "__typename": "Token_sum_fields", + "tokenId": "10000000000000000000000000000000000000000000001000000000000000000000123456811" + } + }, + "nodes": [ + { + "__typename": "Token", + "id": "tok-1" + }, + { + "__typename": "Token", + "id": "tok-10" + }, + { + "__typename": "Token", + "id": "tok-2" + }, + { + "__typename": "Token", + "id": "tok-3" + }, + { + "__typename": "Token", + "id": "tok-4" + }, + { + "__typename": "Token", + "id": "tok-5" + }, + { + "__typename": "Token", + "id": "tok-6" + }, + { + "__typename": "Token", + "id": "tok-7" + }, + { + "__typename": "Token", + "id": "tok-8" + }, + { + "__typename": "Token", + "id": "tok-9" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-typename-nested-everywhere.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-typename-nested-everywhere.json new file mode 100644 index 0000000000..371a0ad6cd --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-typename-nested-everywhere.json @@ -0,0 +1,129 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}) { __typename id gravatar { __typename id } tokens(order_by: {id: asc}) { __typename id collection { __typename id } } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "__typename": "User", + "id": "user \"quoted\" 🚀", + "gravatar": null, + "tokens": [ + { + "__typename": "Token", + "id": "tok-8", + "collection": { + "__typename": "NftCollection", + "id": "coll-2" + } + } + ] + }, + { + "__typename": "User", + "id": "user-1", + "gravatar": { + "__typename": "Gravatar", + "id": "grav-1" + }, + "tokens": [ + { + "__typename": "Token", + "id": "tok-1", + "collection": { + "__typename": "NftCollection", + "id": "coll-1" + } + }, + { + "__typename": "Token", + "id": "tok-2", + "collection": { + "__typename": "NftCollection", + "id": "coll-1" + } + }, + { + "__typename": "Token", + "id": "tok-7", + "collection": null + } + ] + }, + { + "__typename": "User", + "id": "user-2", + "gravatar": { + "__typename": "Gravatar", + "id": "grav-2" + }, + "tokens": [ + { + "__typename": "Token", + "id": "tok-3", + "collection": { + "__typename": "NftCollection", + "id": "coll-1" + } + }, + { + "__typename": "Token", + "id": "tok-4", + "collection": { + "__typename": "NftCollection", + "id": "coll-2" + } + } + ] + }, + { + "__typename": "User", + "id": "user-3", + "gravatar": null, + "tokens": [ + { + "__typename": "Token", + "id": "tok-5", + "collection": { + "__typename": "NftCollection", + "id": "coll-2" + } + } + ] + }, + { + "__typename": "User", + "id": "user-4", + "gravatar": null, + "tokens": [ + { + "__typename": "Token", + "id": "tok-10", + "collection": { + "__typename": "NftCollection", + "id": "coll-1" + } + }, + { + "__typename": "Token", + "id": "tok-9", + "collection": { + "__typename": "NftCollection", + "id": "coll-2" + } + } + ] + }, + { + "__typename": "User", + "id": "user-dangling", + "gravatar": null, + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-bool-exp-token.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-bool-exp-token.json new file mode 100644 index 0000000000..f409bbcadf --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-bool-exp-token.json @@ -0,0 +1,44 @@ +{ + "role": "public", + "request": { + "query": "query ($w: Token_bool_exp!) { Token(where: $w, order_by: {id: asc}) { id tokenId } }", + "variables": { + "w": { + "tokenId": { + "_gte": 7 + } + } + } + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-10", + "tokenId": "10" + }, + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-6", + "tokenId": "123456789" + }, + { + "id": "tok-7", + "tokenId": "7" + }, + { + "id": "tok-8", + "tokenId": "8" + }, + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-boolean-string-in-where-coerced.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-boolean-string-in-where-coerced.json new file mode 100644 index 0000000000..8ea4a1029b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-boolean-string-in-where-coerced.json @@ -0,0 +1,36 @@ +{ + "role": "public", + "request": { + "query": "query ($b: Boolean!) { EntityWithAllNonArrayTypes(where: {bool: {_eq: $b}}, order_by: {id: asc}) { id bool } }", + "variables": { + "b": "true" + } + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-1", + "bool": true + }, + { + "id": "scalar-empty", + "bool": true + }, + { + "id": "scalar-extremes", + "bool": true + }, + { + "id": "scalar-neg-inf", + "bool": true + }, + { + "id": "scalar-unicode", + "bool": true + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-enum-scalar-accounttype.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-enum-scalar-accounttype.json new file mode 100644 index 0000000000..5ffaae7d6a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-enum-scalar-accounttype.json @@ -0,0 +1,24 @@ +{ + "role": "public", + "request": { + "query": "query ($t: accounttype!) { User(where: {accountType: {_eq: $t}}, order_by: {id: asc}) { id accountType } }", + "variables": { + "t": "ADMIN" + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1", + "accountType": "ADMIN" + }, + { + "id": "user-4", + "accountType": "ADMIN" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-float8-number.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-float8-number.json new file mode 100644 index 0000000000..434135b1bb --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-float8-number.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "query ($f: float8!) { EntityWithAllNonArrayTypes(where: {float_: {_gt: $f}}, order_by: {id: asc}) { id float_ } }", + "variables": { + "f": 0.5 + } + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-1", + "float_": "1.5" + }, + { + "id": "scalar-extremes", + "float_": "1.7976931348623157e+308" + }, + { + "id": "scalar-special-float", + "float_": "Infinity" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-float8-string-coerced.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-float8-string-coerced.json new file mode 100644 index 0000000000..8b2ce67ee1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-float8-string-coerced.json @@ -0,0 +1,20 @@ +{ + "role": "public", + "request": { + "query": "query ($f: float8!) { EntityWithAllNonArrayTypes(where: {float_: {_eq: $f}}, order_by: {id: asc}) { id float_ } }", + "variables": { + "f": "1.5" + } + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-1", + "float_": "1.5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-int-limit-offset.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-int-limit-offset.json new file mode 100644 index 0000000000..18adff154c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-int-limit-offset.json @@ -0,0 +1,26 @@ +{ + "role": "public", + "request": { + "query": "query ($l: Int!, $o: Int!) { SimpleEntity(order_by: {id: asc}, limit: $l, offset: $o) { id } }", + "variables": { + "l": 3, + "o": 2 + } + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-jsonb-nested-overflow-number.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-jsonb-nested-overflow-number.json new file mode 100644 index 0000000000..f80168b351 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-jsonb-nested-overflow-number.json @@ -0,0 +1,13 @@ +{ + "role": "public", + "request": { + "query": "query ($j: jsonb!) { EntityWithAllTypes(where: {json: {_contains: $j}}, order_by: {id: asc}) { id } }", + "rawVariables": "{\"j\":{\"nested\":-9e999}}" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-jsonb-object-contains.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-jsonb-object-contains.json new file mode 100644 index 0000000000..891dd27ae0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-jsonb-object-contains.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "query ($j: jsonb!) { EntityWithAllTypes(where: {json: {_contains: $j}}, order_by: {id: asc}) { id json } }", + "variables": { + "j": { + "kind": "object" + } + } + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1", + "json": { + "n": 1, + "kind": "object", + "nested": { + "a": [ + 1, + 2 + ] + } + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-jsonb-unicode-contains.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-jsonb-unicode-contains.json new file mode 100644 index 0000000000..4789e2413c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-jsonb-unicode-contains.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "query ($j: jsonb!) { EntityWithAllTypes(where: {json: {_contains: $j}}, order_by: {id: asc}) { id } }", + "variables": { + "j": { + "héllo": "wörld 🚀" + } + } + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-json-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-missing-variables-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-missing-variables-object.json new file mode 100644 index 0000000000..f8e9172f04 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-missing-variables-object.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "query ($w: SimpleEntity_bool_exp) { SimpleEntity(where: $w, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-nested-relationship-args.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-nested-relationship-args.json new file mode 100644 index 0000000000..377e02d482 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-nested-relationship-args.json @@ -0,0 +1,85 @@ +{ + "role": "public", + "request": { + "query": "query ($tw: Token_bool_exp, $tl: Int, $tord: [Token_order_by!]) { User(order_by: {id: asc}) { id tokens(where: $tw, limit: $tl, order_by: $tord) { id tokenId } } }", + "variables": { + "tw": { + "tokenId": { + "_gte": 0 + } + }, + "tl": 2, + "tord": [ + { + "tokenId": "desc" + }, + { + "id": "asc" + } + ] + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "tokens": [ + { + "id": "tok-8", + "tokenId": "8" + } + ] + }, + { + "id": "user-1", + "tokens": [ + { + "id": "tok-7", + "tokenId": "7" + }, + { + "id": "tok-2", + "tokenId": "1" + } + ] + }, + { + "id": "user-2", + "tokens": [ + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-3", + "tokenId": "2" + } + ] + }, + { + "id": "user-3", + "tokens": [] + }, + { + "id": "user-4", + "tokens": [ + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "tok-10", + "tokenId": "10" + } + ] + }, + { + "id": "user-dangling", + "tokens": [] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-null-for-nullable-args.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-null-for-nullable-args.json new file mode 100644 index 0000000000..971bea52a5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-null-for-nullable-args.json @@ -0,0 +1,47 @@ +{ + "role": "public", + "request": { + "query": "query ($w: SimpleEntity_bool_exp, $l: Int) { SimpleEntity(where: $w, limit: $l, order_by: {id: asc}) { id } }", + "variables": { + "w": null, + "l": null + } + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-as-number.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-as-number.json new file mode 100644 index 0000000000..7f17898c77 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-as-number.json @@ -0,0 +1,20 @@ +{ + "role": "public", + "request": { + "query": "query ($n: numeric!) { Token(where: {tokenId: {_eq: $n}}, order_by: {id: asc}) { id tokenId } }", + "variables": { + "n": 8 + } + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-8", + "tokenId": "8" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-as-string.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-as-string.json new file mode 100644 index 0000000000..c030771b9e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-as-string.json @@ -0,0 +1,20 @@ +{ + "role": "public", + "request": { + "query": "query ($n: numeric!) { Token(where: {tokenId: {_eq: $n}}, order_by: {id: asc}) { id tokenId } }", + "variables": { + "n": "1000000000000000000000000000000" + } + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-decimal-number.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-decimal-number.json new file mode 100644 index 0000000000..f4eac2599d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-decimal-number.json @@ -0,0 +1,20 @@ +{ + "role": "public", + "request": { + "query": "query ($n: numeric!) { EntityWithAllNonArrayTypes(where: {bigDecimal: {_eq: $n}}, order_by: {id: asc}) { id bigDecimal } }", + "variables": { + "n": 1.25 + } + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-1", + "bigDecimal": "1.25" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-overflow-number.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-overflow-number.json new file mode 100644 index 0000000000..ff2737249d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-numeric-overflow-number.json @@ -0,0 +1,13 @@ +{ + "role": "public", + "request": { + "query": "query ($n: numeric!) { Token(where: {tokenId: {_eq: $n}}, order_by: {id: asc}) { id tokenId } }", + "rawVariables": "{\"n\":1e400}" + }, + "status": 200, + "body": { + "data": { + "Token": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-order-by-enum-in-object-default.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-order-by-enum-in-object-default.json new file mode 100644 index 0000000000..673e58add1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-order-by-enum-in-object-default.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "query ($dir: order_by = desc) { SimpleEntity(order_by: [{id: $dir}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-9" + }, + { + "id": "simple-8" + }, + { + "id": "simple-7" + }, + { + "id": "simple-6" + }, + { + "id": "simple-5" + }, + { + "id": "simple-4" + }, + { + "id": "simple-3" + }, + { + "id": "simple-2" + }, + { + "id": "simple-10" + }, + { + "id": "simple-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-order-by-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-order-by-list.json new file mode 100644 index 0000000000..b4858d8f29 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-order-by-list.json @@ -0,0 +1,46 @@ +{ + "role": "public", + "request": { + "query": "query ($ord: [Token_order_by!]!) { Token(order_by: $ord, limit: 4) { id tokenId owner_id } }", + "variables": { + "ord": [ + { + "owner_id": "asc" + }, + { + "tokenId": "desc" + }, + { + "id": "asc" + } + ] + } + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-8", + "tokenId": "8", + "owner_id": "user \"quoted\" 🚀" + }, + { + "id": "tok-7", + "tokenId": "7", + "owner_id": "user-1" + }, + { + "id": "tok-2", + "tokenId": "1", + "owner_id": "user-1" + }, + { + "id": "tok-1", + "tokenId": "0", + "owner_id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-select-column-distinct-on.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-select-column-distinct-on.json new file mode 100644 index 0000000000..a88f0a0ed8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-select-column-distinct-on.json @@ -0,0 +1,42 @@ +{ + "role": "public", + "request": { + "query": "query ($cols: [Token_select_column!]!) { Token(distinct_on: $cols, order_by: [{owner_id: asc}, {tokenId: desc}, {id: asc}]) { id owner_id } }", + "variables": { + "cols": [ + "owner_id" + ] + } + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-8", + "owner_id": "user \"quoted\" 🚀" + }, + { + "id": "tok-7", + "owner_id": "user-1" + }, + { + "id": "tok-4", + "owner_id": "user-2" + }, + { + "id": "tok-5", + "owner_id": "user-3" + }, + { + "id": "tok-9", + "owner_id": "user-4" + }, + { + "id": "tok-6", + "owner_id": "user-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-select-column-single-value-coercion.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-select-column-single-value-coercion.json new file mode 100644 index 0000000000..a7b5f862f2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-select-column-single-value-coercion.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "query ($cols: [Token_select_column!]!) { Token(distinct_on: $cols, order_by: [{collection_id: asc}, {tokenId: desc}, {id: asc}]) { id collection_id } }", + "variables": { + "cols": "collection_id" + } + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-10", + "collection_id": "coll-1" + }, + { + "id": "tok-9", + "collection_id": "coll-2" + }, + { + "id": "tok-7", + "collection_id": "coll-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-string-list-in.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-string-list-in.json new file mode 100644 index 0000000000..17b2bb5340 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-string-list-in.json @@ -0,0 +1,26 @@ +{ + "role": "public", + "request": { + "query": "query ($ids: [String!]!) { SimpleEntity(where: {id: {_in: $ids}}, order_by: {id: asc}) { id } }", + "variables": { + "ids": [ + "simple-1", + "simple-9", + "missing" + ] + } + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-string-list-single-value-coercion.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-string-list-single-value-coercion.json new file mode 100644 index 0000000000..e742a0414e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-string-list-single-value-coercion.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "query ($ids: [String!]!) { SimpleEntity(where: {id: {_in: $ids}}, order_by: {id: asc}) { id } }", + "variables": { + "ids": "simple-1" + } + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-string-where.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-string-where.json new file mode 100644 index 0000000000..1d71bd6948 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-string-where.json @@ -0,0 +1,20 @@ +{ + "role": "public", + "request": { + "query": "query ($v: String!) { SimpleEntity(where: {value: {_eq: $v}}, order_by: {id: asc}) { id value } }", + "variables": { + "v": "v3" + } + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-3", + "value": "v3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-timestamptz-string.json b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-timestamptz-string.json new file mode 100644 index 0000000000..efcf36168d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/vr-var-timestamptz-string.json @@ -0,0 +1,20 @@ +{ + "role": "public", + "request": { + "query": "query ($ts: timestamptz!) { EntityWithTimestamp(where: {timestamp: {_eq: $ts}}, order_by: {id: asc}) { id timestamp } }", + "variables": { + "ts": "2024-01-15T12:34:56.123456+00:00" + } + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp": [ + { + "id": "ts-micro", + "timestamp": "2024-01-15T12:34:56.123456+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-and-empty-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-and-empty-list.json new file mode 100644 index 0000000000..ad4d9a3962 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-and-empty-list.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {_and: []}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-and-explicit.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-and-explicit.json new file mode 100644 index 0000000000..46ba930b5c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-and-explicit.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {_and: [{accountType: {_eq: \"USER\"}}, {updatesCountOnUserForTesting: {_gt: 0}}]}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-and-implicit.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-and-implicit.json new file mode 100644 index 0000000000..27f8b60e95 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-and-implicit.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {accountType: {_eq: \"USER\"}, gravatar_id: {_is_null: false}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-2" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-array-relationship.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-array-relationship.json new file mode 100644 index 0000000000..2423624df3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-array-relationship.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {tokens: {tokenId: {_gte: \"9\"}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-2" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-bool-eq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-bool-eq.json new file mode 100644 index 0000000000..fdf48ba2c8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-bool-eq.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {bool: {_eq: true}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-1" + }, + { + "id": "scalar-empty" + }, + { + "id": "scalar-extremes" + }, + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-empty-bool-exp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-empty-bool-exp.json new file mode 100644 index 0000000000..6e077d5b08 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-empty-bool-exp.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-empty-string-eq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-empty-string-eq.json new file mode 100644 index 0000000000..bffe93b92f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-empty-string-eq.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {string: {_eq: \"\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-empty" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-enum-eq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-enum-eq.json new file mode 100644 index 0000000000..11b5a30219 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-enum-eq.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {accountType: {_eq: \"ADMIN\"}}, order_by: {id: asc}) { id accountType } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1", + "accountType": "ADMIN" + }, + { + "id": "user-4", + "accountType": "ADMIN" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-enum-in.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-enum-in.json new file mode 100644 index 0000000000..ce915f13d3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-enum-in.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {accountType: {_in: [\"ADMIN\", \"USER\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-enum-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-enum-neq.json new file mode 100644 index 0000000000..740184a95d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-enum-neq.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(where: {size: {_neq: \"SMALL\"}}, order_by: {id: asc}) { id size } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-2", + "size": "MEDIUM" + }, + { + "id": "grav-3", + "size": "LARGE" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-float-eq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-float-eq.json new file mode 100644 index 0000000000..5f15c8a7b5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-float-eq.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {float_: {_eq: \"3.14159\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-float-gt.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-float-gt.json new file mode 100644 index 0000000000..f66d9a3824 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-float-gt.json @@ -0,0 +1,29 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {float_: {_gt: 0}}, order_by: {id: asc}) { id float_ } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-1", + "float_": "1.5" + }, + { + "id": "scalar-extremes", + "float_": "1.7976931348623157e+308" + }, + { + "id": "scalar-quotes", + "float_": "0.1" + }, + { + "id": "scalar-special-float", + "float_": "Infinity" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-ilike.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-ilike.json new file mode 100644 index 0000000000..2953f5b71b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-ilike.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {address: {_ilike: \"0XAAAA%\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-int-comparisons.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-int-comparisons.json new file mode 100644 index 0000000000..fc25064ac4 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-int-comparisons.json @@ -0,0 +1,29 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {updatesCountOnUserForTesting: {_gte: 0, _lt: 100}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "updatesCountOnUserForTesting": 5 + }, + { + "id": "user-1", + "updatesCountOnUserForTesting": 0 + }, + { + "id": "user-2", + "updatesCountOnUserForTesting": 42 + }, + { + "id": "user-dangling", + "updatesCountOnUserForTesting": 7 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-int-negative.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-int-negative.json new file mode 100644 index 0000000000..c277f1542f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-int-negative.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {updatesCountOnUserForTesting: {_lt: 0}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-4", + "updatesCountOnUserForTesting": -2147483648 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-iregex.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-iregex.json new file mode 100644 index 0000000000..8ba27c00f6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-iregex.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {value: {_iregex: \"^V[13]$\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-is-null-false.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-is-null-false.json new file mode 100644 index 0000000000..26a600b603 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-is-null-false.json @@ -0,0 +1,22 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {gravatar_id: {_is_null: false}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-is-null-true.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-is-null-true.json new file mode 100644 index 0000000000..c4de860909 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-is-null-true.json @@ -0,0 +1,22 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {gravatar_id: {_is_null: true}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-like-escape-chars.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-like-escape-chars.json new file mode 100644 index 0000000000..5ee3d6c917 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-like-escape-chars.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {string: {_like: \"%\\\"double\\\"%\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-quotes" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-like.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-like.json new file mode 100644 index 0000000000..a0b8fdc002 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-like.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {address: {_like: \"%000001\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-multiple-ops-same-column.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-multiple-ops-same-column.json new file mode 100644 index 0000000000..6148eebd8a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-multiple-ops-same-column.json @@ -0,0 +1,29 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {tokenId: {_gte: 1, _lte: 10, _neq: 8}}, order_by: {id: asc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-10", + "tokenId": "10" + }, + { + "id": "tok-2", + "tokenId": "1" + }, + { + "id": "tok-3", + "tokenId": "2" + }, + { + "id": "tok-7", + "tokenId": "7" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-nested-and-or-not.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-nested-and-or-not.json new file mode 100644 index 0000000000..03ef8d40da --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-nested-and-or-not.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {_or: [{_and: [{accountType: {_eq: \"ADMIN\"}}, {_not: {updatesCountOnUserForTesting: {_lt: 0}}}]}, {id: {_like: \"%quoted%\"}}]}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-nilike.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-nilike.json new file mode 100644 index 0000000000..bf56a578e8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-nilike.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {address: {_nilike: \"0XAAAA%02\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-niregex.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-niregex.json new file mode 100644 index 0000000000..669089856e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-niregex.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {value: {_niregex: \"^V[13]$\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-nlike.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-nlike.json new file mode 100644 index 0000000000..b163b8a3e1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-nlike.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {address: {_nlike: \"%000001\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-not.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-not.json new file mode 100644 index 0000000000..00634403c1 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-not.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {_not: {accountType: {_eq: \"ADMIN\"}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-nsimilar.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-nsimilar.json new file mode 100644 index 0000000000..40ff82ec4f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-nsimilar.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {value: {_nsimilar: \"v(1|2)\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-10" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-eq-int-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-eq-int-literal.json new file mode 100644 index 0000000000..b0ea8daf7f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-eq-int-literal.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {tokenId: {_eq: 1}}, order_by: {id: asc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-2", + "tokenId": "1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-eq-string-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-eq-string-literal.json new file mode 100644 index 0000000000..5e30835f92 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-eq-string-literal.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {tokenId: {_eq: \"1000000000000000000000000000000\"}}, order_by: {id: asc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-gt-huge.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-gt-huge.json new file mode 100644 index 0000000000..d246e1b985 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-gt-huge.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {tokenId: {_gt: \"99999999999999999999999999999\"}}, order_by: {id: asc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-in-mixed.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-in-mixed.json new file mode 100644 index 0000000000..644dfa4e57 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-in-mixed.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {tokenId: {_in: [0, \"8\", 10]}}, order_by: {id: asc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-1", + "tokenId": "0" + }, + { + "id": "tok-10", + "tokenId": "10" + }, + { + "id": "tok-8", + "tokenId": "8" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-negative.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-negative.json new file mode 100644 index 0000000000..fc2e2c1900 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-numeric-negative.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {tokenId: {_lt: 0}}, order_by: {id: asc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-5", + "tokenId": "-5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-object-relationship.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-object-relationship.json new file mode 100644 index 0000000000..19b1b6c805 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-object-relationship.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar(where: {owner: {accountType: {_eq: \"ADMIN\"}}}, order_by: {id: asc}) { id owner { id } } }" + }, + "status": 200, + "body": { + "data": { + "Gravatar": [ + { + "id": "grav-1", + "owner": { + "id": "user-1" + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-or-empty-list.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-or-empty-list.json new file mode 100644 index 0000000000..3e1aa2e709 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-or-empty-list.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {_or: []}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-or.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-or.json new file mode 100644 index 0000000000..4bd3b15a1c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-or.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {_or: [{id: {_eq: \"user-1\"}}, {id: {_eq: \"user-2\"}}]}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + }, + { + "id": "user-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-regex.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-regex.json new file mode 100644 index 0000000000..b8a7a856a0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-regex.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {value: {_regex: \"^v[13]$\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-relationship-is-null-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-relationship-is-null-object.json new file mode 100644 index 0000000000..f9e22b4712 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-relationship-is-null-object.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {gravatar: {id: {_is_null: false}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + }, + { + "id": "user-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-relationship-nested-two-levels.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-relationship-nested-two-levels.json new file mode 100644 index 0000000000..c060db3c41 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-relationship-nested-two-levels.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ NftCollection(where: {tokens: {owner: {accountType: {_eq: \"ADMIN\"}}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "NftCollection": [ + { + "id": "coll-1" + }, + { + "id": "coll-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-similar.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-similar.json new file mode 100644 index 0000000000..a20184b373 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-similar.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {value: {_similar: \"v(1|2)\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-eq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-eq.json new file mode 100644 index 0000000000..730aa64786 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-eq.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {value: {_eq: \"v3\"}}, order_by: {id: asc}) { id value } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-3", + "value": "v3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-gt-lt.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-gt-lt.json new file mode 100644 index 0000000000..d13bcb0ca3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-gt-lt.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {id: {_gt: \"simple-2\", _lt: \"simple-5\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-3" + }, + { + "id": "simple-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-gte-lte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-gte-lte.json new file mode 100644 index 0000000000..250549f4fc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-gte-lte.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {id: {_gte: \"simple-2\", _lte: \"simple-5\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-in-empty.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-in-empty.json new file mode 100644 index 0000000000..0e8de928b7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-in-empty.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {id: {_in: []}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-in.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-in.json new file mode 100644 index 0000000000..81bfaa0ae6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-in.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {id: {_in: [\"simple-1\", \"simple-3\", \"missing\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-neq.json new file mode 100644 index 0000000000..ae9950cc90 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-neq.json @@ -0,0 +1,40 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {value: {_neq: \"v3\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-nin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-nin.json new file mode 100644 index 0000000000..ba0a757a51 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-string-nin.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {id: {_nin: [\"simple-1\", \"simple-2\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-10" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-timestamp-eq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-timestamp-eq.json new file mode 100644 index 0000000000..6d197e31b6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-timestamp-eq.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp(where: {timestamp: {_eq: \"2024-01-15T12:34:56.123456+00:00\"}}, order_by: {id: asc}) { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp": [ + { + "id": "ts-micro", + "timestamp": "2024-01-15T12:34:56.123456+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-timestamp-range.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-timestamp-range.json new file mode 100644 index 0000000000..8f194d13ab --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-timestamp-range.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp(where: {timestamp: {_gte: \"1970-01-01\", _lt: \"2025-01-01\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp": [ + { + "id": "ts-epoch" + }, + { + "id": "ts-micro" + }, + { + "id": "ts-milli" + }, + { + "id": "ts-zoned" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-timestamp-zoned-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-timestamp-zoned-literal.json new file mode 100644 index 0000000000..5b8adb4620 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-timestamp-zoned-literal.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp(where: {timestamp: {_eq: \"2024-06-15T12:00:00+09:30\"}}, order_by: {id: asc}) { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp": [ + { + "id": "ts-zoned", + "timestamp": "2024-06-15T02:30:00+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-unicode-value.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-unicode-value.json new file mode 100644 index 0000000000..4f25d3f955 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-unicode-value.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {string: {_eq: \"héllo wörld 中文测试 🚀🎉\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-variables-bool-exp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-variables-bool-exp.json new file mode 100644 index 0000000000..2454e7c007 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-variables-bool-exp.json @@ -0,0 +1,26 @@ +{ + "role": "public", + "request": { + "query": "query ($w: User_bool_exp!) { User(where: $w, order_by: {id: asc}) { id } }", + "variables": { + "w": { + "accountType": { + "_eq": "ADMIN" + } + } + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/where-variables-nested-exp.json b/packages/e2e-tests/fixtures/differential/snapshots/default/where-variables-nested-exp.json new file mode 100644 index 0000000000..fef059c7e8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/where-variables-nested-exp.json @@ -0,0 +1,37 @@ +{ + "role": "public", + "request": { + "query": "query ($w: User_bool_exp) { User(where: $w, order_by: {id: asc}) { id } }", + "variables": { + "w": { + "_or": [ + { + "id": { + "_eq": "user-1" + } + }, + { + "tokens": { + "tokenId": { + "_eq": 8 + } + } + } + ] + } + } + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-contains-contained-in.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-contains-contained-in.json new file mode 100644 index 0000000000..56f661b377 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-contains-contained-in.json @@ -0,0 +1,35 @@ +{ + "role": "public", + "request": { + "query": "{ contains: EntityWithAllTypes(where: {arrayOfStrings: {_contains: [\"two\"]}}, order_by: {id: asc}) { id arrayOfStrings } containedIn: EntityWithAllTypes(where: {arrayOfStrings: {_contained_in: [\"a\", \"b\", \"one\", \"two\", \"three\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "contains": [ + { + "id": "all-1", + "arrayOfStrings": [ + "one", + "two", + "three" + ] + } + ], + "containedIn": [ + { + "id": "all-1" + }, + { + "id": "all-empty-arrays" + }, + { + "id": "all-json-number" + }, + { + "id": "all-json-string" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-eq-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-eq-neq.json new file mode 100644 index 0000000000..e8b19fdd51 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-eq-neq.json @@ -0,0 +1,44 @@ +{ + "role": "public", + "request": { + "query": "{ eq: EntityWithAllTypes(where: {arrayOfStrings: {_eq: [\"one\", \"two\", \"three\"]}}, order_by: {id: asc}) { id arrayOfStrings } neq: EntityWithAllTypes(where: {arrayOfStrings: {_neq: [\"one\", \"two\", \"three\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "eq": [ + { + "id": "all-1", + "arrayOfStrings": [ + "one", + "two", + "three" + ] + } + ], + "neq": [ + { + "id": "all-array-edge" + }, + { + "id": "all-empty-arrays" + }, + { + "id": "all-json-bool" + }, + { + "id": "all-json-null" + }, + { + "id": "all-json-number" + }, + { + "id": "all-json-string" + }, + { + "id": "all-json-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-gt-gte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-gt-gte.json new file mode 100644 index 0000000000..2845d65496 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-gt-gte.json @@ -0,0 +1,72 @@ +{ + "role": "public", + "request": { + "query": "{ gt: EntityWithAllTypes(where: {arrayOfStrings: {_gt: [\"b\"]}}, order_by: {id: asc}) { id arrayOfStrings } gte: EntityWithAllTypes(where: {arrayOfStrings: {_gte: [\"b\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "gt": [ + { + "id": "all-1", + "arrayOfStrings": [ + "one", + "two", + "three" + ] + }, + { + "id": "all-array-edge", + "arrayOfStrings": [ + "with,comma", + "with}brace", + "with\"quote", + "with'single", + "", + " leading space", + "emoji 🚀", + "back\\slash" + ] + }, + { + "id": "all-json-bool", + "arrayOfStrings": [ + "e" + ] + }, + { + "id": "all-json-null", + "arrayOfStrings": [ + "c" + ] + }, + { + "id": "all-json-unicode", + "arrayOfStrings": [ + "d" + ] + } + ], + "gte": [ + { + "id": "all-1" + }, + { + "id": "all-array-edge" + }, + { + "id": "all-json-bool" + }, + { + "id": "all-json-null" + }, + { + "id": "all-json-number" + }, + { + "id": "all-json-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-in-database-error.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-in-database-error.json new file mode 100644 index 0000000000..9c3aeccb1a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-in-database-error.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {arrayOfStrings: {_in: [[\"a\"], [\"one\", \"two\", \"three\"]]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "database query error", + "extensions": { + "path": "$", + "code": "unexpected" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-is-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-is-null.json new file mode 100644 index 0000000000..978b9ce91e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-is-null.json @@ -0,0 +1,38 @@ +{ + "role": "public", + "request": { + "query": "{ isNull: EntityWithAllTypes(where: {arrayOfStrings: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllTypes(where: {arrayOfStrings: {_is_null: false}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "isNull": [], + "notNull": [ + { + "id": "all-1" + }, + { + "id": "all-array-edge" + }, + { + "id": "all-empty-arrays" + }, + { + "id": "all-json-bool" + }, + { + "id": "all-json-null" + }, + { + "id": "all-json-number" + }, + { + "id": "all-json-string" + }, + { + "id": "all-json-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-lt-lte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-lt-lte.json new file mode 100644 index 0000000000..e4e6946e59 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-array-lt-lte.json @@ -0,0 +1,34 @@ +{ + "role": "public", + "request": { + "query": "{ lt: EntityWithAllTypes(where: {arrayOfStrings: {_lt: [\"b\"]}}, order_by: {id: asc}) { id arrayOfStrings } lte: EntityWithAllTypes(where: {arrayOfStrings: {_lte: [\"b\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "lt": [ + { + "id": "all-empty-arrays", + "arrayOfStrings": [] + }, + { + "id": "all-json-string", + "arrayOfStrings": [ + "a" + ] + } + ], + "lte": [ + { + "id": "all-empty-arrays" + }, + { + "id": "all-json-number" + }, + { + "id": "all-json-string" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-eq-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-eq-neq.json new file mode 100644 index 0000000000..8216338ae6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-eq-neq.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ eq: raw_events(where: {event_id: {_eq: \"4611686018427387905\"}}, order_by: {serial: asc}) { serial event_id } neq: raw_events(where: {event_id: {_neq: \"4611686018427387905\"}}, order_by: {serial: asc}) { serial } }" + }, + "status": 200, + "body": { + "data": { + "eq": [ + { + "serial": "2", + "event_id": "4611686018427387905" + } + ], + "neq": [ + { + "serial": "1" + }, + { + "serial": "3" + }, + { + "serial": "4" + }, + { + "serial": "5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-eq-unquoted-64bit-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-eq-unquoted-64bit-literal.json new file mode 100644 index 0000000000..20ec4edae6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-eq-unquoted-64bit-literal.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(where: {event_id: {_eq: 4611686018427387904}}, order_by: {serial: asc}) { serial event_id } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "1", + "event_id": "4611686018427387904" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-gt-gte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-gt-gte.json new file mode 100644 index 0000000000..9eeb295231 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-gt-gte.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ gt: raw_events(where: {event_id: {_gt: \"4611686018427387905\"}}, order_by: {serial: asc}) { serial event_id } gte: raw_events(where: {event_id: {_gte: \"4611686018427387905\"}}, order_by: {serial: asc}) { serial } }" + }, + "status": 200, + "body": { + "data": { + "gt": [ + { + "serial": "3", + "event_id": "4611686018427387906" + } + ], + "gte": [ + { + "serial": "2" + }, + { + "serial": "3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-in-nin-mixed-literals.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-in-nin-mixed-literals.json new file mode 100644 index 0000000000..b519098465 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-in-nin-mixed-literals.json @@ -0,0 +1,32 @@ +{ + "role": "public", + "request": { + "query": "{ in: raw_events(where: {event_id: {_in: [1, \"4611686018427387906\"]}}, order_by: {serial: asc}) { serial event_id } nin: raw_events(where: {event_id: {_nin: [1, \"4611686018427387906\"]}}, order_by: {serial: asc}) { serial } }" + }, + "status": 200, + "body": { + "data": { + "in": [ + { + "serial": "3", + "event_id": "4611686018427387906" + }, + { + "serial": "4", + "event_id": "1" + } + ], + "nin": [ + { + "serial": "1" + }, + { + "serial": "2" + }, + { + "serial": "5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-is-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-is-null.json new file mode 100644 index 0000000000..130e1a02e8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-is-null.json @@ -0,0 +1,29 @@ +{ + "role": "public", + "request": { + "query": "{ isNull: raw_events(where: {event_id: {_is_null: true}}, order_by: {serial: asc}) { serial } notNull: raw_events(where: {event_id: {_is_null: false}}, order_by: {serial: asc}) { serial } }" + }, + "status": 200, + "body": { + "data": { + "isNull": [], + "notNull": [ + { + "serial": "1" + }, + { + "serial": "2" + }, + { + "serial": "3" + }, + { + "serial": "4" + }, + { + "serial": "5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-lt-lte-int-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-lt-lte-int-literal.json new file mode 100644 index 0000000000..93e9292f81 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bigint-lt-lte-int-literal.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ lt: raw_events(where: {event_id: {_lt: 2}}, order_by: {serial: asc}) { serial event_id } lte: raw_events(where: {event_id: {_lte: 2}}, order_by: {serial: asc}) { serial } }" + }, + "status": 200, + "body": { + "data": { + "lt": [ + { + "serial": "4", + "event_id": "1" + } + ], + "lte": [ + { + "serial": "4" + }, + { + "serial": "5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-eq-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-eq-neq.json new file mode 100644 index 0000000000..a77a05aa82 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-eq-neq.json @@ -0,0 +1,42 @@ +{ + "role": "public", + "request": { + "query": "{ eq: EntityWithAllNonArrayTypes(where: {bool: {_eq: false}}, order_by: {id: asc}) { id bool } neq: EntityWithAllNonArrayTypes(where: {bool: {_neq: false}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "eq": [ + { + "id": "scalar-nulls", + "bool": false + }, + { + "id": "scalar-quotes", + "bool": false + }, + { + "id": "scalar-special-float", + "bool": false + } + ], + "neq": [ + { + "id": "scalar-1" + }, + { + "id": "scalar-empty" + }, + { + "id": "scalar-extremes" + }, + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-gt-gte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-gt-gte.json new file mode 100644 index 0000000000..2806b8df21 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-gt-gte.json @@ -0,0 +1,45 @@ +{ + "role": "public", + "request": { + "query": "{ gt: EntityWithAllNonArrayTypes(where: {bool: {_gt: false}}, order_by: {id: asc}) { id } gte: EntityWithAllNonArrayTypes(where: {bool: {_gte: true}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "gt": [ + { + "id": "scalar-1" + }, + { + "id": "scalar-empty" + }, + { + "id": "scalar-extremes" + }, + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-unicode" + } + ], + "gte": [ + { + "id": "scalar-1" + }, + { + "id": "scalar-empty" + }, + { + "id": "scalar-extremes" + }, + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-in-nin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-in-nin.json new file mode 100644 index 0000000000..ebe0607fc4 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-in-nin.json @@ -0,0 +1,39 @@ +{ + "role": "public", + "request": { + "query": "{ in: EntityWithAllNonArrayTypes(where: {bool: {_in: [false]}}, order_by: {id: asc}) { id } nin: EntityWithAllNonArrayTypes(where: {bool: {_nin: [false]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "in": [ + { + "id": "scalar-nulls" + }, + { + "id": "scalar-quotes" + }, + { + "id": "scalar-special-float" + } + ], + "nin": [ + { + "id": "scalar-1" + }, + { + "id": "scalar-empty" + }, + { + "id": "scalar-extremes" + }, + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-is-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-is-null.json new file mode 100644 index 0000000000..da0763d9df --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-is-null.json @@ -0,0 +1,44 @@ +{ + "role": "public", + "request": { + "query": "{ isNull: EntityWithAllNonArrayTypes(where: {optBool: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optBool: {_is_null: false}}, order_by: {id: asc}) { id optBool } }" + }, + "status": 200, + "body": { + "data": { + "isNull": [ + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-nulls" + }, + { + "id": "scalar-special-float" + } + ], + "notNull": [ + { + "id": "scalar-1", + "optBool": true + }, + { + "id": "scalar-empty", + "optBool": false + }, + { + "id": "scalar-extremes", + "optBool": false + }, + { + "id": "scalar-quotes", + "optBool": false + }, + { + "id": "scalar-unicode", + "optBool": true + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-lt-lte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-lt-lte.json new file mode 100644 index 0000000000..b77962f382 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-bool-lt-lte.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ lt: EntityWithAllNonArrayTypes(where: {bool: {_lt: true}}, order_by: {id: asc}) { id } lte: EntityWithAllNonArrayTypes(where: {bool: {_lte: false}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "lt": [ + { + "id": "scalar-nulls" + }, + { + "id": "scalar-quotes" + }, + { + "id": "scalar-special-float" + } + ], + "lte": [ + { + "id": "scalar-nulls" + }, + { + "id": "scalar-quotes" + }, + { + "id": "scalar-special-float" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-eq-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-eq-neq.json new file mode 100644 index 0000000000..0ab594f6bf --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-eq-neq.json @@ -0,0 +1,35 @@ +{ + "role": "public", + "request": { + "query": "{ eq: User(where: {accountType: {_eq: \"ADMIN\"}}, order_by: {id: asc}) { id accountType } neq: User(where: {accountType: {_neq: \"ADMIN\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "eq": [ + { + "id": "user-1", + "accountType": "ADMIN" + }, + { + "id": "user-4", + "accountType": "ADMIN" + } + ], + "neq": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-gt-gte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-gt-gte.json new file mode 100644 index 0000000000..cbf0714dde --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-gt-gte.json @@ -0,0 +1,49 @@ +{ + "role": "public", + "request": { + "query": "{ gt: User(where: {accountType: {_gt: \"ADMIN\"}}, order_by: {id: asc}) { id accountType } gte: User(where: {accountType: {_gte: \"ADMIN\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "gt": [ + { + "id": "user \"quoted\" 🚀", + "accountType": "USER" + }, + { + "id": "user-2", + "accountType": "USER" + }, + { + "id": "user-3", + "accountType": "USER" + }, + { + "id": "user-dangling", + "accountType": "USER" + } + ], + "gte": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-in-nin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-in-nin.json new file mode 100644 index 0000000000..8d9c527d92 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-in-nin.json @@ -0,0 +1,26 @@ +{ + "role": "public", + "request": { + "query": "{ in: Gravatar(where: {size: {_in: [\"SMALL\", \"LARGE\"]}}, order_by: {id: asc}) { id size } nin: Gravatar(where: {size: {_nin: [\"SMALL\", \"LARGE\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "in": [ + { + "id": "grav-1", + "size": "SMALL" + }, + { + "id": "grav-3", + "size": "LARGE" + } + ], + "nin": [ + { + "id": "grav-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-is-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-is-null.json new file mode 100644 index 0000000000..95c26e7263 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-is-null.json @@ -0,0 +1,44 @@ +{ + "role": "public", + "request": { + "query": "{ isNull: EntityWithAllNonArrayTypes(where: {optEnumField: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optEnumField: {_is_null: false}}, order_by: {id: asc}) { id optEnumField } }" + }, + "status": 200, + "body": { + "data": { + "isNull": [ + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-nulls" + }, + { + "id": "scalar-special-float" + } + ], + "notNull": [ + { + "id": "scalar-1", + "optEnumField": "USER" + }, + { + "id": "scalar-empty", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-extremes", + "optEnumField": "ADMIN" + }, + { + "id": "scalar-quotes", + "optEnumField": "USER" + }, + { + "id": "scalar-unicode", + "optEnumField": "USER" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-lt-lte-declaration-order.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-lt-lte-declaration-order.json new file mode 100644 index 0000000000..42cde5d510 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-enum-lt-lte-declaration-order.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ lt: Gravatar(where: {size: {_lt: \"MEDIUM\"}}, order_by: {id: asc}) { id size } lte: Gravatar(where: {size: {_lte: \"MEDIUM\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "lt": [ + { + "id": "grav-1", + "size": "SMALL" + } + ], + "lte": [ + { + "id": "grav-1" + }, + { + "id": "grav-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-infinity-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-infinity-literal.json new file mode 100644 index 0000000000..87077e3b72 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-infinity-literal.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {float_: {_eq: \"Infinity\"}}, order_by: {id: asc}) { id float_ } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-special-float", + "float_": "Infinity" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-nan.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-nan.json new file mode 100644 index 0000000000..6b04c141e8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-nan.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {optFloat: {_eq: \"NaN\"}}, order_by: {id: asc}) { id optFloat } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-special-float", + "optFloat": "NaN" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-neq.json new file mode 100644 index 0000000000..303f7bb632 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-neq.json @@ -0,0 +1,40 @@ +{ + "role": "public", + "request": { + "query": "{ eq: EntityWithAllNonArrayTypes(where: {float_: {_eq: \"-3.14159\"}}, order_by: {id: asc}) { id float_ } neq: EntityWithAllNonArrayTypes(where: {float_: {_neq: \"-3.14159\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "eq": [ + { + "id": "scalar-unicode", + "float_": "-3.14159" + } + ], + "neq": [ + { + "id": "scalar-1" + }, + { + "id": "scalar-empty" + }, + { + "id": "scalar-extremes" + }, + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-nulls" + }, + { + "id": "scalar-quotes" + }, + { + "id": "scalar-special-float" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-zero-matches-neg-zero.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-zero-matches-neg-zero.json new file mode 100644 index 0000000000..3384833d07 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-eq-zero-matches-neg-zero.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllNonArrayTypes(where: {optFloat: {_eq: 0}}, order_by: {id: asc}) { id optFloat } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllNonArrayTypes": [ + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-gt-gte-dbl-max.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-gt-gte-dbl-max.json new file mode 100644 index 0000000000..35bab3637a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-gt-gte-dbl-max.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ gt: EntityWithAllNonArrayTypes(where: {float_: {_gt: \"1.7976931348623157e308\"}}, order_by: {id: asc}) { id float_ } gte: EntityWithAllNonArrayTypes(where: {float_: {_gte: \"1.7976931348623157e308\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "gt": [ + { + "id": "scalar-special-float", + "float_": "Infinity" + } + ], + "gte": [ + { + "id": "scalar-extremes" + }, + { + "id": "scalar-special-float" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-in-nin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-in-nin.json new file mode 100644 index 0000000000..4b02e466a3 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-in-nin.json @@ -0,0 +1,42 @@ +{ + "role": "public", + "request": { + "query": "{ in: EntityWithAllNonArrayTypes(where: {float_: {_in: [1.5, \"0.1\", -0.5]}}, order_by: {id: asc}) { id float_ } nin: EntityWithAllNonArrayTypes(where: {float_: {_nin: [1.5, \"0.1\", -0.5]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "in": [ + { + "id": "scalar-1", + "float_": "1.5" + }, + { + "id": "scalar-empty", + "float_": "-0.5" + }, + { + "id": "scalar-quotes", + "float_": "0.1" + } + ], + "nin": [ + { + "id": "scalar-extremes" + }, + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-nulls" + }, + { + "id": "scalar-special-float" + }, + { + "id": "scalar-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-is-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-is-null.json new file mode 100644 index 0000000000..7691ebe22a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-is-null.json @@ -0,0 +1,46 @@ +{ + "role": "public", + "request": { + "query": "{ isNull: EntityWithAllNonArrayTypes(where: {optFloat: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optFloat: {_is_null: false}}, order_by: {id: asc}) { id optFloat } }" + }, + "status": 200, + "body": { + "data": { + "isNull": [ + { + "id": "scalar-nulls" + } + ], + "notNull": [ + { + "id": "scalar-1", + "optFloat": "2.5" + }, + { + "id": "scalar-empty", + "optFloat": "0" + }, + { + "id": "scalar-extremes", + "optFloat": "5e-324" + }, + { + "id": "scalar-neg-inf", + "optFloat": "-0" + }, + { + "id": "scalar-quotes", + "optFloat": "0.2" + }, + { + "id": "scalar-special-float", + "optFloat": "NaN" + }, + { + "id": "scalar-unicode", + "optFloat": "2.718281828459045" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-lt-lte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-lt-lte.json new file mode 100644 index 0000000000..ac23a0e7cd --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-float-lt-lte.json @@ -0,0 +1,32 @@ +{ + "role": "public", + "request": { + "query": "{ lt: EntityWithAllNonArrayTypes(where: {float_: {_lt: \"-0.5\"}}, order_by: {id: asc}) { id float_ } lte: EntityWithAllNonArrayTypes(where: {float_: {_lte: \"-0.5\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "lt": [ + { + "id": "scalar-neg-inf", + "float_": "-Infinity" + }, + { + "id": "scalar-unicode", + "float_": "-3.14159" + } + ], + "lte": [ + { + "id": "scalar-empty" + }, + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-unicode" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-in-duplicate-values.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-in-duplicate-values.json new file mode 100644 index 0000000000..6da646bc0c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-in-duplicate-values.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {tokenId: {_in: [1, 1, \"1\", 2]}}, order_by: {id: asc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-2", + "tokenId": "1" + }, + { + "id": "tok-3", + "tokenId": "2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-in-single-value.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-in-single-value.json new file mode 100644 index 0000000000..15a9575f4c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-in-single-value.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {value: {_in: [\"v7\"]}}, order_by: {id: asc}) { id value } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-7", + "value": "v7" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-eq-int32-max.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-eq-int32-max.json new file mode 100644 index 0000000000..769e4a2602 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-eq-int32-max.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {updatesCountOnUserForTesting: {_eq: 2147483647}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-3", + "updatesCountOnUserForTesting": 2147483647 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-eq-int32-min.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-eq-int32-min.json new file mode 100644 index 0000000000..7813b30288 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-eq-int32-min.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {updatesCountOnUserForTesting: {_eq: -2147483648}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-4", + "updatesCountOnUserForTesting": -2147483648 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-eq-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-eq-neq.json new file mode 100644 index 0000000000..bbf2e5ceec --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-eq-neq.json @@ -0,0 +1,32 @@ +{ + "role": "public", + "request": { + "query": "{ eq: SimulateTestEvent(where: {blockNumber: {_eq: 100}}, order_by: {id: asc}) { id blockNumber } neq: SimulateTestEvent(where: {blockNumber: {_neq: 100}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "eq": [ + { + "id": "sim-1", + "blockNumber": 100 + }, + { + "id": "sim-2", + "blockNumber": 100 + } + ], + "neq": [ + { + "id": "sim-3" + }, + { + "id": "sim-4" + }, + { + "id": "sim-5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-gt-gte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-gt-gte.json new file mode 100644 index 0000000000..b8779a153b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-gt-gte.json @@ -0,0 +1,32 @@ +{ + "role": "public", + "request": { + "query": "{ gt: SimulateTestEvent(where: {logIndex: {_gt: 1}}, order_by: {id: asc}) { id logIndex } gte: SimulateTestEvent(where: {logIndex: {_gte: 1}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "gt": [ + { + "id": "sim-4", + "logIndex": 5 + }, + { + "id": "sim-5", + "logIndex": 2 + } + ], + "gte": [ + { + "id": "sim-2" + }, + { + "id": "sim-4" + }, + { + "id": "sim-5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-in-nin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-in-nin.json new file mode 100644 index 0000000000..ab563ff0d4 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-in-nin.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ in: User(where: {updatesCountOnUserForTesting: {_in: [0, 7, 2147483647]}}, order_by: {id: asc}) { id } nin: User(where: {updatesCountOnUserForTesting: {_nin: [0, 7, 2147483647]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "in": [ + { + "id": "user-1" + }, + { + "id": "user-3" + }, + { + "id": "user-dangling" + } + ], + "nin": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-2" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-is-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-is-null.json new file mode 100644 index 0000000000..d3a8e08728 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-is-null.json @@ -0,0 +1,44 @@ +{ + "role": "public", + "request": { + "query": "{ isNull: EntityWithAllNonArrayTypes(where: {optInt: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optInt: {_is_null: false}}, order_by: {id: asc}) { id optInt } }" + }, + "status": 200, + "body": { + "data": { + "isNull": [ + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-nulls" + }, + { + "id": "scalar-special-float" + } + ], + "notNull": [ + { + "id": "scalar-1", + "optInt": 10 + }, + { + "id": "scalar-empty", + "optInt": 0 + }, + { + "id": "scalar-extremes", + "optInt": -2147483648 + }, + { + "id": "scalar-quotes", + "optInt": 3 + }, + { + "id": "scalar-unicode", + "optInt": 7 + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-lt-lte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-lt-lte.json new file mode 100644 index 0000000000..49ae5a6f4c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-int-lt-lte.json @@ -0,0 +1,32 @@ +{ + "role": "public", + "request": { + "query": "{ lt: User(where: {updatesCountOnUserForTesting: {_lt: 5}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } lte: User(where: {updatesCountOnUserForTesting: {_lte: 5}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "lt": [ + { + "id": "user-1", + "updatesCountOnUserForTesting": 0 + }, + { + "id": "user-4", + "updatesCountOnUserForTesting": -2147483648 + } + ], + "lte": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-is-null-false-with-like.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-is-null-false-with-like.json new file mode 100644 index 0000000000..3a8c5146c6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-is-null-false-with-like.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {gravatar_id: {_is_null: false, _like: \"grav-%\"}}, order_by: {id: asc}) { id gravatar_id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1", + "gravatar_id": "grav-1" + }, + { + "id": "user-2", + "gravatar_id": "grav-2" + }, + { + "id": "user-dangling", + "gravatar_id": "grav-missing" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-is-null-true-with-eq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-is-null-true-with-eq.json new file mode 100644 index 0000000000..ef64e492cb --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-is-null-true-with-eq.json @@ -0,0 +1,12 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {gravatar_id: {_is_null: true, _eq: \"grav-1\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-cast-string-eq-scalar.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-cast-string-eq-scalar.json new file mode 100644 index 0000000000..95fd168cd6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-cast-string-eq-scalar.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {json: {_cast: {String: {_eq: \"\\\"just a string\\\"\"}}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-json-string" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-cast-string-like.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-cast-string-like.json new file mode 100644 index 0000000000..243d001dfc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-cast-string-like.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {json: {_cast: {String: {_like: \"%\\\"kind\\\"%\"}}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-eq-empty-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-eq-empty-object.json new file mode 100644 index 0000000000..48578b0d11 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-eq-empty-object.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {json: {_eq: {}}}, order_by: {id: asc}) { id json } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-empty-arrays", + "json": {} + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-eq-nested-object.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-eq-nested-object.json new file mode 100644 index 0000000000..94a74450c5 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-eq-nested-object.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithAllTypes(where: {json: {_eq: {kind: \"object\", n: 1, nested: {a: [1, 2]}}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithAllTypes": [ + { + "id": "all-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-eq-object-literal.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-eq-object-literal.json new file mode 100644 index 0000000000..08c80b6822 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-jsonb-eq-object-literal.json @@ -0,0 +1,21 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(where: {params: {_eq: {from: \"0x0\", to: \"0x1\", value: \"100\"}}}, order_by: {serial: asc}) { serial params } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "1", + "params": { + "to": "0x1", + "from": "0x0", + "value": "100" + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-eq-76-digits.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-eq-76-digits.json new file mode 100644 index 0000000000..991285f6ca --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-eq-76-digits.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ Token(where: {tokenId: {_eq: \"9999999999999999999999999999999999999999999999999999999999999999999999999999\"}}, order_by: {id: asc}) { id tokenId } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-9", + "tokenId": "9999999999999999999999999999999999999999999999999999999999999999999999999999" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-eq-neq-trailing-zero.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-eq-neq-trailing-zero.json new file mode 100644 index 0000000000..c1d65e9424 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-eq-neq-trailing-zero.json @@ -0,0 +1,31 @@ +{ + "role": "public", + "request": { + "query": "{ eq: EntityWithBigDecimal(where: {bigDecimal: {_eq: \"1.1\"}}, order_by: {id: asc}) { id bigDecimal } neq: EntityWithBigDecimal(where: {bigDecimal: {_neq: \"1.1\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "eq": [ + { + "id": "bd-2", + "bigDecimal": "1.10" + } + ], + "neq": [ + { + "id": "bd-1" + }, + { + "id": "bd-3" + }, + { + "id": "bd-4" + }, + { + "id": "bd-5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-eq-tiny-fraction.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-eq-tiny-fraction.json new file mode 100644 index 0000000000..5fe52ceb7f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-eq-tiny-fraction.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithBigDecimal(where: {bigDecimal: {_eq: \"0.000000000000000001\"}}, order_by: {id: asc}) { id bigDecimal } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithBigDecimal": [ + { + "id": "bd-5", + "bigDecimal": "0.000000000000000001" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-gt-gte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-gt-gte.json new file mode 100644 index 0000000000..25f3d089e0 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-gt-gte.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ gt: EntityWithBigDecimal(where: {bigDecimal: {_gt: \"1.1\"}}, order_by: {id: asc}) { id bigDecimal } gte: EntityWithBigDecimal(where: {bigDecimal: {_gte: \"1.10\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "gt": [ + { + "id": "bd-4", + "bigDecimal": "123456789.123456789" + } + ], + "gte": [ + { + "id": "bd-2" + }, + { + "id": "bd-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-in-nin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-in-nin.json new file mode 100644 index 0000000000..7129a7942c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-in-nin.json @@ -0,0 +1,48 @@ +{ + "role": "public", + "request": { + "query": "{ in: Token(where: {tokenId: {_in: [\"-5\", 7, \"1000000000000000000000000000000\"]}}, order_by: {id: asc}) { id tokenId } nin: Token(where: {tokenId: {_nin: [\"-5\", 7, \"1000000000000000000000000000000\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "in": [ + { + "id": "tok-4", + "tokenId": "1000000000000000000000000000000" + }, + { + "id": "tok-5", + "tokenId": "-5" + }, + { + "id": "tok-7", + "tokenId": "7" + } + ], + "nin": [ + { + "id": "tok-1" + }, + { + "id": "tok-10" + }, + { + "id": "tok-2" + }, + { + "id": "tok-3" + }, + { + "id": "tok-6" + }, + { + "id": "tok-8" + }, + { + "id": "tok-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-is-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-is-null.json new file mode 100644 index 0000000000..a41f7fed04 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-is-null.json @@ -0,0 +1,44 @@ +{ + "role": "public", + "request": { + "query": "{ isNull: EntityWithAllNonArrayTypes(where: {optBigInt: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optBigInt: {_is_null: false}}, order_by: {id: asc}) { id optBigInt } }" + }, + "status": 200, + "body": { + "data": { + "isNull": [ + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-nulls" + }, + { + "id": "scalar-special-float" + } + ], + "notNull": [ + { + "id": "scalar-1", + "optBigInt": "200" + }, + { + "id": "scalar-empty", + "optBigInt": "0" + }, + { + "id": "scalar-extremes", + "optBigInt": "-9999999999999999999999999999999999999999999999999999999999999999999999999999" + }, + { + "id": "scalar-quotes", + "optBigInt": "8" + }, + { + "id": "scalar-unicode", + "optBigInt": "-42" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-lt-lte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-lt-lte.json new file mode 100644 index 0000000000..1c925e9f79 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-numeric-lt-lte.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ lt: EntityWithBigDecimal(where: {bigDecimal: {_lt: 0}}, order_by: {id: asc}) { id bigDecimal } lte: EntityWithBigDecimal(where: {bigDecimal: {_lte: 0}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "lt": [ + { + "id": "bd-3", + "bigDecimal": "-1.10" + } + ], + "lte": [ + { + "id": "bd-1" + }, + { + "id": "bd-3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-eq-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-eq-neq.json new file mode 100644 index 0000000000..73a3127b9a --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-eq-neq.json @@ -0,0 +1,34 @@ +{ + "role": "public", + "request": { + "query": "{ eq: User(where: {address: {_eq: \"0xaaaa000000000000000000000000000000000003\"}}, order_by: {id: asc}) { id address } neq: User(where: {address: {_neq: \"0xaaaa000000000000000000000000000000000003\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "eq": [ + { + "id": "user-3", + "address": "0xaaaa000000000000000000000000000000000003" + } + ], + "neq": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-gt-gte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-gt-gte.json new file mode 100644 index 0000000000..bc6a4d8b7b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-gt-gte.json @@ -0,0 +1,30 @@ +{ + "role": "public", + "request": { + "query": "{ gt: User(where: {address: {_gt: \"0xaaaa000000000000000000000000000000000004\"}}, order_by: {id: asc}) { id } gte: User(where: {address: {_gte: \"0xaaaa000000000000000000000000000000000004\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "gt": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-dangling" + } + ], + "gte": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-ilike-nilike.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-ilike-nilike.json new file mode 100644 index 0000000000..ed6ccd7b9b --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-ilike-nilike.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ ilike: User(where: {address: {_ilike: \"0XAAAA%3\"}}, order_by: {id: asc}) { id } nilike: User(where: {address: {_nilike: \"0XAAAA%3\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "ilike": [ + { + "id": "user-3" + } + ], + "nilike": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-in-nin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-in-nin.json new file mode 100644 index 0000000000..3e2d877bde --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-in-nin.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ in: User(where: {address: {_in: [\"0xaaaa000000000000000000000000000000000002\", \"0xaaaa000000000000000000000000000000000005\", \"0xmissing\"]}}, order_by: {id: asc}) { id } nin: User(where: {address: {_nin: [\"0xaaaa000000000000000000000000000000000002\", \"0xaaaa000000000000000000000000000000000005\", \"0xmissing\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "in": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-2" + } + ], + "nin": [ + { + "id": "user-1" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-iregex-niregex.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-iregex-niregex.json new file mode 100644 index 0000000000..18788416da --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-iregex-niregex.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ iregex: User(where: {address: {_iregex: \"^0XAAAA.*[56]$\"}}, order_by: {id: asc}) { id } niregex: User(where: {address: {_niregex: \"^0XAAAA.*[56]$\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "iregex": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-dangling" + } + ], + "niregex": [ + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-is-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-is-null.json new file mode 100644 index 0000000000..9822cf34d8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-is-null.json @@ -0,0 +1,32 @@ +{ + "role": "public", + "request": { + "query": "{ isNull: User(where: {address: {_is_null: true}}, order_by: {id: asc}) { id } notNull: User(where: {address: {_is_null: false}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "isNull": [], + "notNull": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-like-nlike.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-like-nlike.json new file mode 100644 index 0000000000..8bbc3fb89c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-like-nlike.json @@ -0,0 +1,32 @@ +{ + "role": "public", + "request": { + "query": "{ like: User(where: {address: {_like: \"%00000_\"}}, order_by: {id: asc}) { id } nlike: User(where: {address: {_nlike: \"%00000_\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "like": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ], + "nlike": [] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-lt-lte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-lt-lte.json new file mode 100644 index 0000000000..97f5e8f65d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-lt-lte.json @@ -0,0 +1,24 @@ +{ + "role": "public", + "request": { + "query": "{ lt: User(where: {address: {_lt: \"0xaaaa000000000000000000000000000000000002\"}}, order_by: {id: asc}) { id } lte: User(where: {address: {_lte: \"0xaaaa000000000000000000000000000000000002\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "lt": [ + { + "id": "user-1" + } + ], + "lte": [ + { + "id": "user-1" + }, + { + "id": "user-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-nin-empty.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-nin-empty.json new file mode 100644 index 0000000000..f972e6b3e8 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-nin-empty.json @@ -0,0 +1,43 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(where: {id: {_nin: []}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-regex-nregex.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-regex-nregex.json new file mode 100644 index 0000000000..d19cd0d6ba --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-regex-nregex.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ regex: User(where: {address: {_regex: \"000[12]$\"}}, order_by: {id: asc}) { id } nregex: User(where: {address: {_nregex: \"000[12]$\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "regex": [ + { + "id": "user-1" + }, + { + "id": "user-2" + } + ], + "nregex": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-similar-nsimilar.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-similar-nsimilar.json new file mode 100644 index 0000000000..c4164aa179 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-text-similar-nsimilar.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ similar: User(where: {address: {_similar: \"0xaaaa%(1|2)\"}}, order_by: {id: asc}) { id } nsimilar: User(where: {address: {_nsimilar: \"0xaaaa%(1|2)\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "similar": [ + { + "id": "user-1" + }, + { + "id": "user-2" + } + ], + "nsimilar": [ + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-3" + }, + { + "id": "user-4" + }, + { + "id": "user-dangling" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-eq-neq.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-eq-neq.json new file mode 100644 index 0000000000..b7b2291f55 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-eq-neq.json @@ -0,0 +1,34 @@ +{ + "role": "public", + "request": { + "query": "{ eq: EntityWithTimestamp(where: {timestamp: {_eq: \"2024-01-15T12:34:56.123+00:00\"}}, order_by: {id: asc}) { id timestamp } neq: EntityWithTimestamp(where: {timestamp: {_neq: \"2024-01-15T12:34:56.123+00:00\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "eq": [ + { + "id": "ts-milli", + "timestamp": "2024-01-15T12:34:56.123+00:00" + } + ], + "neq": [ + { + "id": "ts-epoch" + }, + { + "id": "ts-future" + }, + { + "id": "ts-micro" + }, + { + "id": "ts-pre-epoch" + }, + { + "id": "ts-zoned" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-eq-normalized-offset.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-eq-normalized-offset.json new file mode 100644 index 0000000000..89f43a60bc --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-eq-normalized-offset.json @@ -0,0 +1,17 @@ +{ + "role": "public", + "request": { + "query": "{ EntityWithTimestamp(where: {timestamp: {_eq: \"2024-06-15T02:30:00+00:00\"}}, order_by: {id: asc}) { id timestamp } }" + }, + "status": 200, + "body": { + "data": { + "EntityWithTimestamp": [ + { + "id": "ts-zoned", + "timestamp": "2024-06-15T02:30:00+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-gt-gte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-gt-gte.json new file mode 100644 index 0000000000..1d60184567 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-gt-gte.json @@ -0,0 +1,30 @@ +{ + "role": "public", + "request": { + "query": "{ gt: EntityWithTimestamp(where: {timestamp: {_gt: \"2024-01-15T12:34:56.123456+00:00\"}}, order_by: {id: asc}) { id } gte: EntityWithTimestamp(where: {timestamp: {_gte: \"2024-01-15T12:34:56.123456+00:00\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "gt": [ + { + "id": "ts-future" + }, + { + "id": "ts-zoned" + } + ], + "gte": [ + { + "id": "ts-future" + }, + { + "id": "ts-micro" + }, + { + "id": "ts-zoned" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-in-nin.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-in-nin.json new file mode 100644 index 0000000000..cc9d4d2805 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-in-nin.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ in: EntityWithTimestamp(where: {timestamp: {_in: [\"1970-01-01T00:00:00Z\", \"9999-12-31T23:59:59.999999+00:00\"]}}, order_by: {id: asc}) { id } nin: EntityWithTimestamp(where: {timestamp: {_nin: [\"1970-01-01T00:00:00Z\", \"9999-12-31T23:59:59.999999+00:00\"]}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "in": [ + { + "id": "ts-epoch" + }, + { + "id": "ts-future" + } + ], + "nin": [ + { + "id": "ts-micro" + }, + { + "id": "ts-milli" + }, + { + "id": "ts-pre-epoch" + }, + { + "id": "ts-zoned" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-is-null.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-is-null.json new file mode 100644 index 0000000000..114cd969b6 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-is-null.json @@ -0,0 +1,44 @@ +{ + "role": "public", + "request": { + "query": "{ isNull: EntityWithAllNonArrayTypes(where: {optTimestamp: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optTimestamp: {_is_null: false}}, order_by: {id: asc}) { id optTimestamp } }" + }, + "status": 200, + "body": { + "data": { + "isNull": [ + { + "id": "scalar-neg-inf" + }, + { + "id": "scalar-nulls" + }, + { + "id": "scalar-special-float" + } + ], + "notNull": [ + { + "id": "scalar-1", + "optTimestamp": "2024-01-15T12:34:56.789123+00:00" + }, + { + "id": "scalar-empty", + "optTimestamp": "2024-07-04T00:00:00.12+00:00" + }, + { + "id": "scalar-extremes", + "optTimestamp": "1969-12-31T23:59:59.999999+00:00" + }, + { + "id": "scalar-quotes", + "optTimestamp": "2024-03-10T10:00:00+00:00" + }, + { + "id": "scalar-unicode", + "optTimestamp": "2024-12-26T02:30:00+00:00" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-lt-lte.json b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-lt-lte.json new file mode 100644 index 0000000000..6cbbf8758e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/default/wm-ts-lt-lte.json @@ -0,0 +1,25 @@ +{ + "role": "public", + "request": { + "query": "{ lt: EntityWithTimestamp(where: {timestamp: {_lt: \"1970-01-01T00:00:00+00:00\"}}, order_by: {id: asc}) { id timestamp } lte: EntityWithTimestamp(where: {timestamp: {_lte: \"1970-01-01T00:00:00+00:00\"}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "lt": [ + { + "id": "ts-pre-epoch", + "timestamp": "1969-07-20T20:17:40+00:00" + } + ], + "lte": [ + { + "id": "ts-epoch" + }, + { + "id": "ts-pre-epoch" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/introspection-full-public-limited.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/introspection-full-public-limited.json new file mode 100644 index 0000000000..ee12b4e382 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/introspection-full-public-limited.json @@ -0,0 +1,25844 @@ +{ + "role": "public", + "request": { + "query": "\nquery IntrospectionQuery {\n __schema {\n queryType { name }\n mutationType { name }\n subscriptionType { name }\n types { ...FullType }\n directives { name description locations args { ...InputValue } }\n }\n}\nfragment FullType on __Type {\n kind name description\n fields(includeDeprecated: true) {\n name description\n args { ...InputValue }\n type { ...TypeRef }\n isDeprecated deprecationReason\n }\n inputFields { ...InputValue }\n interfaces { ...TypeRef }\n enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason }\n possibleTypes { ...TypeRef }\n}\nfragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue }\nfragment TypeRef on __Type {\n kind name\n ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } }\n}" + }, + "status": 200, + "body": { + "data": { + "__schema": { + "queryType": { + "name": "query_root" + }, + "mutationType": null, + "subscriptionType": { + "name": "subscription_root" + }, + "types": [ + { + "kind": "OBJECT", + "name": "A", + "description": "columns and relationships of \"A\"", + "fields": [ + { + "name": "b", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "B", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "b_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_aggregate_order_by", + "description": "order by aggregate values of table \"A\"", + "fields": null, + "inputFields": [ + { + "name": "count", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "max", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_max_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "min", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_min_order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "description": "Boolean expression to filter rows from the table \"A\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "b", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "b_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_max_order_by", + "description": "order by max() on columns of table \"A\"", + "fields": null, + "inputFields": [ + { + "name": "b_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_min_order_by", + "description": "order by min() on columns of table \"A\"", + "fields": null, + "inputFields": [ + { + "name": "b_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "description": "Ordering options when selecting data from \"A\".", + "fields": null, + "inputFields": [ + { + "name": "b", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "b_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "A_select_column", + "description": "select columns of table \"A\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "b_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_stream_cursor_input", + "description": "Streaming cursor of the table \"A\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "A_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "b_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optionalStringToTestLinkedEntities", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "B", + "description": "columns and relationships of \"B\"", + "fields": [ + { + "name": "a", + "description": "An array relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "c", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "C", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "c_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "description": "Boolean expression to filter rows from the table \"B\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "a", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "c", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "c_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "description": "Ordering options when selecting data from \"B\".", + "fields": null, + "inputFields": [ + { + "name": "a_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_aggregate_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "c", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "c_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "B_select_column", + "description": "select columns of table \"B\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "c_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "B_stream_cursor_input", + "description": "Streaming cursor of the table \"B\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "B_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "c_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "Boolean", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "description": "Boolean expression to compare columns of type \"Boolean\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "C", + "description": "columns and relationships of \"C\"", + "fields": [ + { + "name": "a", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "A", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "a_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "d", + "description": "An array relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stringThatIsMirroredToA", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "description": "Boolean expression to filter rows from the table \"C\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "a", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "a_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "d", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stringThatIsMirroredToA", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "description": "Ordering options when selecting data from \"C\".", + "fields": null, + "inputFields": [ + { + "name": "a", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "a_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "d_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_aggregate_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stringThatIsMirroredToA", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "C_select_column", + "description": "select columns of table \"C\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "a_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stringThatIsMirroredToA", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "C_stream_cursor_input", + "description": "Streaming cursor of the table \"C\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "C_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "a_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stringThatIsMirroredToA", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "description": "columns and relationships of \"CustomSelectionTestPass\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "description": "Boolean expression to filter rows from the table \"CustomSelectionTestPass\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "description": "Ordering options when selecting data from \"CustomSelectionTestPass\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "description": "select columns of table \"CustomSelectionTestPass\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_stream_cursor_input", + "description": "Streaming cursor of the table \"CustomSelectionTestPass\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "D", + "description": "columns and relationships of \"D\"", + "fields": [ + { + "name": "c", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_aggregate_order_by", + "description": "order by aggregate values of table \"D\"", + "fields": null, + "inputFields": [ + { + "name": "count", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "max", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_max_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "min", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_min_order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "description": "Boolean expression to filter rows from the table \"D\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "c", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_max_order_by", + "description": "order by max() on columns of table \"D\"", + "fields": null, + "inputFields": [ + { + "name": "c", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_min_order_by", + "description": "order by min() on columns of table \"D\"", + "fields": null, + "inputFields": [ + { + "name": "c", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "description": "Ordering options when selecting data from \"D\".", + "fields": null, + "inputFields": [ + { + "name": "c", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "D_select_column", + "description": "select columns of table \"D\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "c", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_stream_cursor_input", + "description": "Streaming cursor of the table \"D\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "D_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "c", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "description": "columns and relationships of \"EntityWith63LenghtName______________________________________one\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWith63LenghtName______________________________________one\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "description": "Ordering options when selecting data from \"EntityWith63LenghtName______________________________________one\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "description": "select columns of table \"EntityWith63LenghtName______________________________________one\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWith63LenghtName______________________________________one\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "description": "columns and relationships of \"EntityWith63LenghtName______________________________________two\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWith63LenghtName______________________________________two\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "description": "Ordering options when selecting data from \"EntityWith63LenghtName______________________________________two\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "description": "select columns of table \"EntityWith63LenghtName______________________________________two\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWith63LenghtName______________________________________two\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "description": "columns and relationships of \"EntityWithAllNonArrayTypes\"", + "fields": [ + { + "name": "bigDecimal", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigInt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bool", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumField", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "float_", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "int_", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigDecimal", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBool", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optEnumField", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optFloat", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optString", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optTimestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "string", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithAllNonArrayTypes\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "description": "Ordering options when selecting data from \"EntityWithAllNonArrayTypes\".", + "fields": null, + "inputFields": [ + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "description": "select columns of table \"EntityWithAllNonArrayTypes\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "bigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimalWithConfig", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bool", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumField", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "float_", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "int_", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBool", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optEnumField", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optFloat", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optString", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optTimestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "string", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithAllNonArrayTypes\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "description": "columns and relationships of \"EntityWithAllTypes\"", + "fields": [ + { + "name": "arrayOfBigDecimals", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfBigInts", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfFloats", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfInts", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfStrings", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimal", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigInt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bool", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumField", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "float_", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "int_", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "json", + "description": null, + "args": [ + { + "name": "path", + "description": "JSON select path", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigDecimal", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBool", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optEnumField", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optFloat", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optString", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optTimestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "string", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithAllTypes\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfBigDecimals", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfBigInts", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfFloats", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfInts", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfStrings", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "json", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "description": "Ordering options when selecting data from \"EntityWithAllTypes\".", + "fields": null, + "inputFields": [ + { + "name": "arrayOfBigDecimals", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfBigInts", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfFloats", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfInts", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "arrayOfStrings", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "json", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "description": "select columns of table \"EntityWithAllTypes\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "arrayOfBigDecimals", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfBigInts", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfFloats", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfInts", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "arrayOfStrings", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigDecimalWithConfig", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bool", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumField", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "float_", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "int_", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "json", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optBool", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optEnumField", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optFloat", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optString", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "optTimestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "string", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithAllTypes\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "arrayOfBigDecimals", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfBigInts", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfFloats", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfInts", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "arrayOfStrings", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigDecimalWithConfig", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "bool", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "enumField", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "float_", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "int_", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "json", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optBool", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optEnumField", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optFloat", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optString", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "optTimestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "string", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "description": "columns and relationships of \"EntityWithBigDecimal\"", + "fields": [ + { + "name": "bigDecimal", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithBigDecimal\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "description": "Ordering options when selecting data from \"EntityWithBigDecimal\".", + "fields": null, + "inputFields": [ + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "description": "select columns of table \"EntityWithBigDecimal\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "bigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithBigDecimal\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "bigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "description": "columns and relationships of \"EntityWithRestrictedReScriptField\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithRestrictedReScriptField\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "description": "Ordering options when selecting data from \"EntityWithRestrictedReScriptField\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "description": "select columns of table \"EntityWithRestrictedReScriptField\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithRestrictedReScriptField\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "description": "columns and relationships of \"EntityWithTimestamp\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "description": "Boolean expression to filter rows from the table \"EntityWithTimestamp\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "description": "Ordering options when selecting data from \"EntityWithTimestamp\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "description": "select columns of table \"EntityWithTimestamp\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_stream_cursor_input", + "description": "Streaming cursor of the table \"EntityWithTimestamp\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "Float", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Float_comparison_exp", + "description": "Boolean expression to compare columns of type \"Float\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Gravatar", + "description": "columns and relationships of \"Gravatar\"", + "fields": [ + { + "name": "displayName", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "imageUrl", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "size", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCount", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "description": "Boolean expression to filter rows from the table \"Gravatar\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "displayName", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "imageUrl", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "size", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "gravatarsize_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCount", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "description": "Ordering options when selecting data from \"Gravatar\".", + "fields": null, + "inputFields": [ + { + "name": "displayName", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "imageUrl", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "size", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCount", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "Gravatar_select_column", + "description": "select columns of table \"Gravatar\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "displayName", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "imageUrl", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "size", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCount", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Gravatar_stream_cursor_input", + "description": "Streaming cursor of the table \"Gravatar\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Gravatar_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "displayName", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "imageUrl", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "size", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCount", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "Int", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Int_array_comparison_exp", + "description": "Boolean expression to compare columns of type \"Int\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_contained_in", + "description": "is the array contained in the given array value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the array contain the given value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "description": "Boolean expression to compare columns of type \"Int\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "NftCollection", + "description": "columns and relationships of \"NftCollection\"", + "fields": [ + { + "name": "contractAddress", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "currentSupply", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "maxSupply", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "symbol", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokens", + "description": "An array relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokens_aggregate", + "description": "An aggregate relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "description": "Boolean expression to filter rows from the table \"NftCollection\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "contractAddress", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "currentSupply", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "maxSupply", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "name", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "symbol", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "description": "Ordering options when selecting data from \"NftCollection\".", + "fields": null, + "inputFields": [ + { + "name": "contractAddress", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "currentSupply", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "maxSupply", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "name", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "symbol", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "NftCollection_select_column", + "description": "select columns of table \"NftCollection\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "contractAddress", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "currentSupply", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "maxSupply", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "symbol", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NftCollection_stream_cursor_input", + "description": "Streaming cursor of the table \"NftCollection\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NftCollection_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "contractAddress", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "currentSupply", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "maxSupply", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "name", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "symbol", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "description": "columns and relationships of \"PostgresNumericPrecisionEntityTester\"", + "fields": [ + { + "name": "exampleBigDecimal", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalArray", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalRequired", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigInt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntArray", + "description": null, + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntRequired", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "description": "Boolean expression to filter rows from the table \"PostgresNumericPrecisionEntityTester\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimal", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArray", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalRequired", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigInt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArray", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntRequired", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "description": "Ordering options when selecting data from \"PostgresNumericPrecisionEntityTester\".", + "fields": null, + "inputFields": [ + { + "name": "exampleBigDecimal", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArray", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalRequired", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigInt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArray", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntRequired", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "description": "select columns of table \"PostgresNumericPrecisionEntityTester\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "exampleBigDecimal", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalArray", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigDecimalRequired", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigInt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntArray", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exampleBigIntRequired", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_stream_cursor_input", + "description": "Streaming cursor of the table \"PostgresNumericPrecisionEntityTester\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "exampleBigDecimal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArray", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalArrayRequired", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalOtherOrder", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigDecimalRequired", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigInt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArray", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigIntArrayRequired", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "exampleBigIntRequired", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SimpleEntity", + "description": "columns and relationships of \"SimpleEntity\"", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "value", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SimpleEntity_aggregate", + "description": "aggregated selection of \"SimpleEntity\"", + "fields": [ + { + "name": "aggregate", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "SimpleEntity_aggregate_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SimpleEntity_aggregate_fields", + "description": "aggregate fields of \"SimpleEntity\"", + "fields": [ + { + "name": "count", + "description": null, + "args": [ + { + "name": "columns", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "distinct", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "max", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "SimpleEntity_max_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "min", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "SimpleEntity_min_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "description": "Boolean expression to filter rows from the table \"SimpleEntity\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "value", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SimpleEntity_max_fields", + "description": "aggregate max on columns", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "value", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SimpleEntity_min_fields", + "description": "aggregate min on columns", + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "value", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "description": "Ordering options when selecting data from \"SimpleEntity\".", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "value", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "description": "select columns of table \"SimpleEntity\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "value", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_stream_cursor_input", + "description": "Streaming cursor of the table \"SimpleEntity\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "value", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "description": "columns and relationships of \"SimulateTestEvent\"", + "fields": [ + { + "name": "blockNumber", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "logIndex", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "description": "Boolean expression to filter rows from the table \"SimulateTestEvent\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "blockNumber", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "logIndex", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "description": "Ordering options when selecting data from \"SimulateTestEvent\".", + "fields": null, + "inputFields": [ + { + "name": "blockNumber", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "logIndex", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "description": "select columns of table \"SimulateTestEvent\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "blockNumber", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "logIndex", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_stream_cursor_input", + "description": "Streaming cursor of the table \"SimulateTestEvent\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "blockNumber", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "logIndex", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "String", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "String_array_comparison_exp", + "description": "Boolean expression to compare columns of type \"String\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_contained_in", + "description": "is the array contained in the given array value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the array contain the given value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "description": "Boolean expression to compare columns of type \"String\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_ilike", + "description": "does the column match the given case-insensitive pattern", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_iregex", + "description": "does the column match the given POSIX regular expression, case insensitive", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_like", + "description": "does the column match the given pattern", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nilike", + "description": "does the column NOT match the given case-insensitive pattern", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_niregex", + "description": "does the column NOT match the given POSIX regular expression, case insensitive", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nlike", + "description": "does the column NOT match the given pattern", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nregex", + "description": "does the column NOT match the given POSIX regular expression, case sensitive", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nsimilar", + "description": "does the column NOT match the given SQL regular expression", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_regex", + "description": "does the column match the given POSIX regular expression, case sensitive", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_similar", + "description": "does the column match the given SQL regular expression", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token", + "description": "columns and relationships of \"Token\"", + "fields": [ + { + "name": "collection", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "collection_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_aggregate", + "description": "aggregated selection of \"Token\"", + "fields": [ + { + "name": "aggregate", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_aggregate_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_bool_exp", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "count", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_bool_exp_count", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_bool_exp_count", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "arguments", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "distinct", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "filter", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "predicate", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_aggregate_fields", + "description": "aggregate fields of \"Token\"", + "fields": [ + { + "name": "avg", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_avg_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "count", + "description": null, + "args": [ + { + "name": "columns", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "distinct", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "max", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_max_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "min", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_min_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_stddev_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev_pop", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_stddev_pop_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev_samp", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_stddev_samp_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sum", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_sum_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "var_pop", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_var_pop_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "var_samp", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_var_samp_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "variance", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Token_variance_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_order_by", + "description": "order by aggregate values of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "avg", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_avg_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "count", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "max", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_max_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "min", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_min_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stddev", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stddev_pop", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_pop_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "stddev_samp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_samp_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sum", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_sum_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "var_pop", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_var_pop_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "var_samp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_var_samp_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "variance", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_variance_order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_avg_fields", + "description": "aggregate avg on columns", + "fields": [ + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_avg_order_by", + "description": "order by avg() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "description": "Boolean expression to filter rows from the table \"Token\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "collection", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "collection_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_max_fields", + "description": "aggregate max on columns", + "fields": [ + { + "name": "collection_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_max_order_by", + "description": "order by max() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "collection_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_min_fields", + "description": "aggregate min on columns", + "fields": [ + { + "name": "collection_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_min_order_by", + "description": "order by min() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "collection_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "description": "Ordering options when selecting data from \"Token\".", + "fields": null, + "inputFields": [ + { + "name": "collection", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "collection_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "Token_select_column", + "description": "select columns of table \"Token\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "collection_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "owner_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokenId", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_stddev_fields", + "description": "aggregate stddev on columns", + "fields": [ + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_order_by", + "description": "order by stddev() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_stddev_pop_fields", + "description": "aggregate stddev_pop on columns", + "fields": [ + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_pop_order_by", + "description": "order by stddev_pop() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_stddev_samp_fields", + "description": "aggregate stddev_samp on columns", + "fields": [ + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stddev_samp_order_by", + "description": "order by stddev_samp() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stream_cursor_input", + "description": "Streaming cursor of the table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "collection_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "owner_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokenId", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_sum_fields", + "description": "aggregate sum on columns", + "fields": [ + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_sum_order_by", + "description": "order by sum() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_var_pop_fields", + "description": "aggregate var_pop on columns", + "fields": [ + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_var_pop_order_by", + "description": "order by var_pop() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_var_samp_fields", + "description": "aggregate var_samp on columns", + "fields": [ + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_var_samp_order_by", + "description": "order by var_samp() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Token_variance_fields", + "description": "aggregate variance on columns", + "fields": [ + { + "name": "tokenId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "Token_variance_order_by", + "description": "order by variance() on columns of table \"Token\"", + "fields": null, + "inputFields": [ + { + "name": "tokenId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User", + "description": "A user of the protocol, keyed by their wallet address.", + "fields": [ + { + "name": "accountType", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "address", + "description": "The user's wallet address, lowercased.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gravatar", + "description": "An object relationship", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gravatar_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokens", + "description": "An array relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tokens_aggregate", + "description": "An aggregate relationship", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_aggregate", + "description": "aggregated selection of \"User\"", + "fields": [ + { + "name": "aggregate", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_aggregate_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_aggregate_fields", + "description": "aggregate fields of \"User\"", + "fields": [ + { + "name": "avg", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_avg_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "count", + "description": null, + "args": [ + { + "name": "columns", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "distinct", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "max", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_max_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "min", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_min_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_stddev_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev_pop", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_stddev_pop_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev_samp", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_stddev_samp_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sum", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_sum_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "var_pop", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_var_pop_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "var_samp", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_var_samp_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "variance", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User_variance_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_avg_fields", + "description": "aggregate avg on columns", + "fields": [ + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "description": "Boolean expression to filter rows from the table \"User\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "accountType", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "address", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_max_fields", + "description": "aggregate max on columns", + "fields": [ + { + "name": "accountType", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "address", + "description": "The user's wallet address, lowercased.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gravatar_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_min_fields", + "description": "aggregate min on columns", + "fields": [ + { + "name": "accountType", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "address", + "description": "The user's wallet address, lowercased.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gravatar_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "description": "Ordering options when selecting data from \"User\".", + "fields": null, + "inputFields": [ + { + "name": "accountType", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "address", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "tokens_aggregate", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_aggregate_order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "User_select_column", + "description": "select columns of table \"User\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "accountType", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "address", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gravatar_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_stddev_fields", + "description": "aggregate stddev on columns", + "fields": [ + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_stddev_pop_fields", + "description": "aggregate stddev_pop on columns", + "fields": [ + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_stddev_samp_fields", + "description": "aggregate stddev_samp on columns", + "fields": [ + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_input", + "description": "Streaming cursor of the table \"User\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "accountType", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "address", + "description": "The user's wallet address, lowercased.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "gravatar_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatesCountOnUserForTesting", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_sum_fields", + "description": "aggregate sum on columns", + "fields": [ + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_var_pop_fields", + "description": "aggregate var_pop on columns", + "fields": [ + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_var_samp_fields", + "description": "aggregate var_samp on columns", + "fields": [ + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "User_variance_fields", + "description": "aggregate variance on columns", + "fields": [ + { + "name": "updatesCountOnUserForTesting", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__Directive", + "description": null, + "fields": [ + { + "name": "args", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__InputValue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isRepeatable", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "locations", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__EnumValue", + "description": null, + "fields": [ + { + "name": "deprecationReason", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isDeprecated", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__Field", + "description": null, + "fields": [ + { + "name": "args", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__InputValue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "deprecationReason", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isDeprecated", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__InputValue", + "description": null, + "fields": [ + { + "name": "defaultValue", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__Schema", + "description": null, + "fields": [ + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "directives", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Directive", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "mutationType", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "queryType", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "subscriptionType", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "types", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "__Type", + "description": null, + "fields": [ + { + "name": "description", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enumValues", + "description": null, + "args": [ + { + "name": "includeDeprecated", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": "false" + } + ], + "type": { + "kind": "OBJECT", + "name": "__EnumValue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "fields", + "description": null, + "args": [ + { + "name": "includeDeprecated", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": "false" + } + ], + "type": { + "kind": "OBJECT", + "name": "__Field", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "inputFields", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__InputValue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "interfaces", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "kind", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "__TypeKind", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "ofType", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "possibleTypes", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "__TypeKind", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ENUM", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "INPUT_OBJECT", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "INTERFACE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "LIST", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NON_NULL", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "OBJECT", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SCALAR", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "UNION", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta", + "description": "columns and relationships of \"_meta\"", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isReady", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "readyAt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_aggregate", + "description": "aggregated selection of \"_meta\"", + "fields": [ + { + "name": "aggregate", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_aggregate_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_aggregate_fields", + "description": "aggregate fields of \"_meta\"", + "fields": [ + { + "name": "avg", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_avg_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "count", + "description": null, + "args": [ + { + "name": "columns", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "distinct", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "max", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_max_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "min", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_min_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_stddev_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev_pop", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_stddev_pop_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev_samp", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_stddev_samp_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sum", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_sum_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "var_pop", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_var_pop_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "var_samp", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_var_samp_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "variance", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "_meta_variance_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_avg_fields", + "description": "aggregate avg on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "description": "Boolean expression to filter rows from the table \"_meta\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "bufferBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chainId", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "eventsProcessed", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Float_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "firstEventBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "isReady", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "progressBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "readyAt", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sourceBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startBlock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_max_fields", + "description": "aggregate max on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "readyAt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_min_fields", + "description": "aggregate min on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "readyAt", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "description": "Ordering options when selecting data from \"_meta\".", + "fields": null, + "inputFields": [ + { + "name": "bufferBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chainId", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "eventsProcessed", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "firstEventBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "isReady", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "progressBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "readyAt", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sourceBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startBlock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "_meta_select_column", + "description": "select columns of table \"_meta\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "bufferBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isReady", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "readyAt", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_stddev_fields", + "description": "aggregate stddev on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_stddev_pop_fields", + "description": "aggregate stddev_pop on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_stddev_samp_fields", + "description": "aggregate stddev_samp on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "_meta_stream_cursor_input", + "description": "Streaming cursor of the table \"_meta\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "_meta_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "bufferBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chainId", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "eventsProcessed", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "firstEventBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "isReady", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "progressBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "readyAt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sourceBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startBlock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_sum_fields", + "description": "aggregate sum on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_var_pop_fields", + "description": "aggregate var_pop on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_var_samp_fields", + "description": "aggregate var_samp on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "_meta_variance_fields", + "description": "aggregate variance on columns", + "fields": [ + { + "name": "bufferBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chainId", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "endBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventsProcessed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "firstEventBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startBlock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "accounttype", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "accounttype_comparison_exp", + "description": "Boolean expression to compare columns of type \"accounttype\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "accounttype", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "bigint", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "bigint_comparison_exp", + "description": "Boolean expression to compare columns of type \"bigint\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "chain_metadata", + "description": "columns and relationships of \"chain_metadata\"", + "fields": [ + { + "name": "block_height", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "end_block", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "first_event_block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "is_hyper_sync", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "latest_fetched_block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "latest_processed_block", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "num_batches_fetched", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "num_events_processed", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "start_block", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "description": "Boolean expression to filter rows from the table \"chain_metadata\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "block_height", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "end_block", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first_event_block_number", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "is_hyper_sync", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Boolean_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_fetched_block_number", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_processed_block", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_batches_fetched", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_events_processed", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Float_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "start_block", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "description": "Ordering options when selecting data from \"chain_metadata\".", + "fields": null, + "inputFields": [ + { + "name": "block_height", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "end_block", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first_event_block_number", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "is_hyper_sync", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_fetched_block_number", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_processed_block", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_batches_fetched", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_events_processed", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "start_block", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "description": "select columns of table \"chain_metadata\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "block_height", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "end_block", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "first_event_block_number", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "is_hyper_sync", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "latest_fetched_block_number", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "latest_processed_block", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "num_batches_fetched", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "num_events_processed", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "start_block", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_stream_cursor_input", + "description": "Streaming cursor of the table \"chain_metadata\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "block_height", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "end_block", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first_event_block_number", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "is_hyper_sync", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_fetched_block_number", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "latest_processed_block", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_batches_fetched", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "num_events_processed", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "start_block", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timestamp_caught_up_to_head_or_endblock", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "cursor_ordering", + "description": "ordering argument of a cursor", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ASC", + "description": "ascending ordering of the cursor", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "DESC", + "description": "descending ordering of the cursor", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "float8", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "float8_array_comparison_exp", + "description": "Boolean expression to compare columns of type \"float8\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_contained_in", + "description": "is the array contained in the given array value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the array contain the given value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "float8_comparison_exp", + "description": "Boolean expression to compare columns of type \"float8\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "float8", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "gravatarsize", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "gravatarsize_comparison_exp", + "description": "Boolean expression to compare columns of type \"gravatarsize\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "gravatarsize", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "jsonb", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "jsonb_cast_exp", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "String", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "description": "Boolean expression to compare columns of type \"jsonb\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_cast", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_cast_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_contained_in", + "description": "is the column contained in the given json value", + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the column contain the given json value at the top level", + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_has_key", + "description": "does the string exist as a top-level key in the column", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_has_keys_all", + "description": "do all of these strings exist as top-level keys in the column", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_has_keys_any", + "description": "do any of these strings exist as top-level keys in the column", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "numeric", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "numeric_array_comparison_exp", + "description": "Boolean expression to compare columns of type \"numeric\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_contained_in", + "description": "is the array contained in the given array value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_contains", + "description": "does the array contain the given value", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_eq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "numeric_comparison_exp", + "description": "Boolean expression to compare columns of type \"numeric\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "numeric", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "order_by", + "description": "column ordering options", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "asc", + "description": "in ascending order, nulls last", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "asc_nulls_first", + "description": "in ascending order, nulls first", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "asc_nulls_last", + "description": "in ascending order, nulls last", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "desc", + "description": "in descending order, nulls first", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "desc_nulls_first", + "description": "in descending order, nulls first", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "desc_nulls_last", + "description": "in descending order, nulls last", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "query_root", + "description": null, + "fields": [ + { + "name": "A", + "description": "fetch data from the table: \"A\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "A_by_pk", + "description": "fetch data from the table: \"A\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "A", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B", + "description": "fetch data from the table: \"B\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "B_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "B", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B_by_pk", + "description": "fetch data from the table: \"B\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "B", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C", + "description": "fetch data from the table: \"C\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "C_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "C", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C_by_pk", + "description": "fetch data from the table: \"C\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "C", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass", + "description": "fetch data from the table: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass_by_pk", + "description": "fetch data from the table: \"CustomSelectionTestPass\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D", + "description": "fetch data from the table: \"D\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D_by_pk", + "description": "fetch data from the table: \"D\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "D", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes", + "description": "fetch data from the table: \"EntityWithAllTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal", + "description": "fetch data from the table: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal_by_pk", + "description": "fetch data from the table: \"EntityWithBigDecimal\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField_by_pk", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp", + "description": "fetch data from the table: \"EntityWithTimestamp\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp_by_pk", + "description": "fetch data from the table: \"EntityWithTimestamp\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar", + "description": "fetch data from the table: \"Gravatar\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Gravatar_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar_by_pk", + "description": "fetch data from the table: \"Gravatar\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection", + "description": "fetch data from the table: \"NftCollection\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "NftCollection_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection_by_pk", + "description": "fetch data from the table: \"NftCollection\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester_by_pk", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity", + "description": "fetch data from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity_aggregate", + "description": "fetch aggregated fields from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity_by_pk", + "description": "fetch data from the table: \"SimpleEntity\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent", + "description": "fetch data from the table: \"SimulateTestEvent\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent_by_pk", + "description": "fetch data from the table: \"SimulateTestEvent\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token", + "description": "fetch data from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token_aggregate", + "description": "fetch aggregated fields from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token_by_pk", + "description": "fetch data from the table: \"Token\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User", + "description": "fetch data from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User_aggregate", + "description": "fetch aggregated fields from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User_by_pk", + "description": "fetch data from the table: \"User\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "_meta", + "description": "fetch data from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "_meta_aggregate", + "description": "fetch aggregated fields from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_metadata", + "description": "fetch data from the table: \"chain_metadata\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "chain_metadata", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events", + "description": "fetch data from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events_aggregate", + "description": "fetch aggregated fields from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events_by_pk", + "description": "fetch data from the table: \"raw_events\" using primary key columns", + "args": [ + { + "name": "serial", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events", + "description": "columns and relationships of \"raw_events\"", + "fields": [ + { + "name": "block_fields", + "description": null, + "args": [ + { + "name": "path", + "description": "JSON select path", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_hash", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "contract_name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "params", + "description": null, + "args": [ + { + "name": "path", + "description": "JSON select path", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "src_address", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "transaction_fields", + "description": null, + "args": [ + { + "name": "path", + "description": "JSON select path", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_aggregate", + "description": "aggregated selection of \"raw_events\"", + "fields": [ + { + "name": "aggregate", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_aggregate_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_aggregate_fields", + "description": "aggregate fields of \"raw_events\"", + "fields": [ + { + "name": "avg", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_avg_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "count", + "description": null, + "args": [ + { + "name": "columns", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "distinct", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "max", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_max_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "min", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_min_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_stddev_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev_pop", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_stddev_pop_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stddev_samp", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_stddev_samp_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sum", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_sum_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "var_pop", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_var_pop_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "var_samp", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_var_samp_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "variance", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "raw_events_variance_fields", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_avg_fields", + "description": "aggregate avg on columns", + "fields": [ + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "description": "Boolean expression to filter rows from the table \"raw_events\". All fields are combined with a logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_and", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_not", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_or", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "block_fields", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_hash", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_number", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_timestamp", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "contract_name", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_id", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "bigint_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_name", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "log_index", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "Int_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "params", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "serial", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "bigint_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "src_address", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "String_comparison_exp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "transaction_fields", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "jsonb_comparison_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_max_fields", + "description": "aggregate max on columns", + "fields": [ + { + "name": "block_hash", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "contract_name", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_name", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "src_address", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_min_fields", + "description": "aggregate min on columns", + "fields": [ + { + "name": "block_hash", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "contract_name", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_name", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "src_address", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "description": "Ordering options when selecting data from \"raw_events\".", + "fields": null, + "inputFields": [ + { + "name": "block_fields", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_hash", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_number", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_timestamp", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "contract_name", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_id", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_name", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "log_index", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "params", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "serial", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "src_address", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "transaction_fields", + "description": null, + "type": { + "kind": "ENUM", + "name": "order_by", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "raw_events_select_column", + "description": "select columns of table \"raw_events\"", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "block_fields", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_hash", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_number", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "contract_name", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_name", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "params", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "src_address", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "transaction_fields", + "description": "column name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_stddev_fields", + "description": "aggregate stddev on columns", + "fields": [ + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_stddev_pop_fields", + "description": "aggregate stddev_pop on columns", + "fields": [ + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_stddev_samp_fields", + "description": "aggregate stddev_samp on columns", + "fields": [ + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "raw_events_stream_cursor_input", + "description": "Streaming cursor of the table \"raw_events\"", + "fields": null, + "inputFields": [ + { + "name": "initial_value", + "description": "Stream column input with initial value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_stream_cursor_value_input", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "ordering", + "description": "cursor ordering", + "type": { + "kind": "ENUM", + "name": "cursor_ordering", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "raw_events_stream_cursor_value_input", + "description": "Initial value of the column from where the streaming should start", + "fields": null, + "inputFields": [ + { + "name": "block_fields", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_hash", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_number", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "block_timestamp", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "chain_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "contract_name", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "event_name", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "log_index", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "params", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "serial", + "description": null, + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "src_address", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "transaction_fields", + "description": null, + "type": { + "kind": "SCALAR", + "name": "jsonb", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_sum_fields", + "description": "aggregate sum on columns", + "fields": [ + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_var_pop_fields", + "description": "aggregate var_pop on columns", + "fields": [ + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_var_samp_fields", + "description": "aggregate var_samp on columns", + "fields": [ + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "raw_events_variance_fields", + "description": "aggregate variance on columns", + "fields": [ + { + "name": "block_number", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "block_timestamp", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "event_id", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "log_index", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "serial", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "subscription_root", + "description": null, + "fields": [ + { + "name": "A", + "description": "fetch data from the table: \"A\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "A_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "A_by_pk", + "description": "fetch data from the table: \"A\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "A", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "A_stream", + "description": "fetch data from the table in a streaming manner: \"A\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "A_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "A_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "A", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B", + "description": "fetch data from the table: \"B\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "B_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "B", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B_by_pk", + "description": "fetch data from the table: \"B\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "B", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B_stream", + "description": "fetch data from the table in a streaming manner: \"B\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "B_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "B_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "B", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C", + "description": "fetch data from the table: \"C\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "C_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "C", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C_by_pk", + "description": "fetch data from the table: \"C\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "C", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C_stream", + "description": "fetch data from the table in a streaming manner: \"C\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "C_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "C_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "C", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass", + "description": "fetch data from the table: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CustomSelectionTestPass_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass_by_pk", + "description": "fetch data from the table: \"CustomSelectionTestPass\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CustomSelectionTestPass_stream", + "description": "fetch data from the table in a streaming manner: \"CustomSelectionTestPass\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "CustomSelectionTestPass_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CustomSelectionTestPass", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D", + "description": "fetch data from the table: \"D\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "D_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D_by_pk", + "description": "fetch data from the table: \"D\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "D", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D_stream", + "description": "fetch data from the table in a streaming manner: \"D\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "D_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "D_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "D", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________one_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________one\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________one_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWith63LenghtName______________________________________one\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________one_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________one", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWith63LenghtName______________________________________two_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two_by_pk", + "description": "fetch data from the table: \"EntityWith63LenghtName______________________________________two\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWith63LenghtName______________________________________two_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWith63LenghtName______________________________________two\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWith63LenghtName______________________________________two_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWith63LenghtName______________________________________two", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllNonArrayTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllNonArrayTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllNonArrayTypes_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithAllNonArrayTypes\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllNonArrayTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllNonArrayTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes", + "description": "fetch data from the table: \"EntityWithAllTypes\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithAllTypes_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes_by_pk", + "description": "fetch data from the table: \"EntityWithAllTypes\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithAllTypes_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithAllTypes\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithAllTypes_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithAllTypes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal", + "description": "fetch data from the table: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithBigDecimal_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal_by_pk", + "description": "fetch data from the table: \"EntityWithBigDecimal\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithBigDecimal_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithBigDecimal\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithBigDecimal_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithBigDecimal", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithRestrictedReScriptField_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField_by_pk", + "description": "fetch data from the table: \"EntityWithRestrictedReScriptField\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithRestrictedReScriptField_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithRestrictedReScriptField\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithRestrictedReScriptField_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithRestrictedReScriptField", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp", + "description": "fetch data from the table: \"EntityWithTimestamp\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityWithTimestamp_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp_by_pk", + "description": "fetch data from the table: \"EntityWithTimestamp\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EntityWithTimestamp_stream", + "description": "fetch data from the table in a streaming manner: \"EntityWithTimestamp\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "EntityWithTimestamp_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EntityWithTimestamp", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar", + "description": "fetch data from the table: \"Gravatar\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Gravatar_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar_by_pk", + "description": "fetch data from the table: \"Gravatar\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Gravatar_stream", + "description": "fetch data from the table in a streaming manner: \"Gravatar\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Gravatar_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Gravatar", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection", + "description": "fetch data from the table: \"NftCollection\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "NftCollection_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection_by_pk", + "description": "fetch data from the table: \"NftCollection\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NftCollection_stream", + "description": "fetch data from the table in a streaming manner: \"NftCollection\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "NftCollection_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NftCollection", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "PostgresNumericPrecisionEntityTester_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester_by_pk", + "description": "fetch data from the table: \"PostgresNumericPrecisionEntityTester\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PostgresNumericPrecisionEntityTester_stream", + "description": "fetch data from the table in a streaming manner: \"PostgresNumericPrecisionEntityTester\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostgresNumericPrecisionEntityTester_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PostgresNumericPrecisionEntityTester", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity", + "description": "fetch data from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity_aggregate", + "description": "fetch aggregated fields from the table: \"SimpleEntity\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimpleEntity_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity_by_pk", + "description": "fetch data from the table: \"SimpleEntity\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimpleEntity_stream", + "description": "fetch data from the table in a streaming manner: \"SimpleEntity\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimpleEntity_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimpleEntity", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent", + "description": "fetch data from the table: \"SimulateTestEvent\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "SimulateTestEvent_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent_by_pk", + "description": "fetch data from the table: \"SimulateTestEvent\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SimulateTestEvent_stream", + "description": "fetch data from the table in a streaming manner: \"SimulateTestEvent\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "SimulateTestEvent_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SimulateTestEvent", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token", + "description": "fetch data from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token_aggregate", + "description": "fetch aggregated fields from the table: \"Token\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "Token_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token_by_pk", + "description": "fetch data from the table: \"Token\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "Token_stream", + "description": "fetch data from the table in a streaming manner: \"Token\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "Token_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "Token_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Token", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User", + "description": "fetch data from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User_aggregate", + "description": "fetch aggregated fields from the table: \"User\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "User_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User_by_pk", + "description": "fetch data from the table: \"User\" using primary key columns", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "User_stream", + "description": "fetch data from the table in a streaming manner: \"User\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "User_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "User_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "_meta", + "description": "fetch data from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "_meta_aggregate", + "description": "fetch aggregated fields from the table: \"_meta\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "_meta_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "_meta_stream", + "description": "fetch data from the table in a streaming manner: \"_meta\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "_meta_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "_meta_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "_meta", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_metadata", + "description": "fetch data from the table: \"chain_metadata\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "chain_metadata_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "chain_metadata", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "chain_metadata_stream", + "description": "fetch data from the table in a streaming manner: \"chain_metadata\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "chain_metadata_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "chain_metadata", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events", + "description": "fetch data from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events_aggregate", + "description": "fetch aggregated fields from the table: \"raw_events\"", + "args": [ + { + "name": "distinct_on", + "description": "distinct select on columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "raw_events_select_column", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "limit", + "description": "limit the number of rows returned", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "offset", + "description": "skip the first n rows. Use only with order_by", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "order_by", + "description": "sort the rows by one or more columns", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_order_by", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events_aggregate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events_by_pk", + "description": "fetch data from the table: \"raw_events\" using primary key columns", + "args": [ + { + "name": "serial", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "bigint", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "raw_events_stream", + "description": "fetch data from the table in a streaming manner: \"raw_events\"", + "args": [ + { + "name": "batch_size", + "description": "maximum number of rows returned in a single batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "cursor", + "description": "cursor to stream the results returned by the query", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "raw_events_stream_cursor_input", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "where", + "description": "filter the rows returned", + "type": { + "kind": "INPUT_OBJECT", + "name": "raw_events_bool_exp", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "raw_events", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "timestamptz", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "timestamptz_comparison_exp", + "description": "Boolean expression to compare columns of type \"timestamptz\". All fields are combined with logical 'AND'.", + "fields": null, + "inputFields": [ + { + "name": "_eq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "_is_null", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_neq", + "description": null, + "type": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "_nin", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "timestamptz", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + } + ], + "directives": [ + { + "name": "include", + "description": "whether this query should be included", + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], + "args": [ + { + "name": "if", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "defaultValue": null + } + ] + }, + { + "name": "skip", + "description": "whether this query should be skipped", + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], + "args": [ + { + "name": "if", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "defaultValue": null + } + ] + }, + { + "name": "cached", + "description": "whether this query should be cached (Hasura Cloud only)", + "locations": [ + "QUERY" + ], + "args": [ + { + "name": "ttl", + "description": "measured in seconds", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": "60" + }, + { + "name": "refresh", + "description": "refresh the cache entry", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "defaultValue": "false" + } + ] + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-admin-not-capped.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-admin-not-capped.json new file mode 100644 index 0000000000..b6cdba879d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-admin-not-capped.json @@ -0,0 +1,43 @@ +{ + "role": "admin", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + }, + { + "id": "simple-6" + }, + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-by-pk-unaffected.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-by-pk-unaffected.json new file mode 100644 index 0000000000..98414b6de2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-by-pk-unaffected.json @@ -0,0 +1,14 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity_by_pk(id: \"simple-9\") { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity_by_pk": { + "id": "simple-9" + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-meta-aggregate-enabled.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-meta-aggregate-enabled.json new file mode 100644 index 0000000000..6dd6d6ed59 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-meta-aggregate-enabled.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ _meta_aggregate { aggregate { count } } }" + }, + "status": 200, + "body": { + "data": { + "_meta_aggregate": { + "aggregate": { + "count": 2 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-nested-relationship-capped.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-nested-relationship-capped.json new file mode 100644 index 0000000000..7c28644474 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-nested-relationship-capped.json @@ -0,0 +1,27 @@ +{ + "role": "public", + "request": { + "query": "{ User(where: {id: {_eq: \"user-1\"}}) { id tokens(order_by: {id: asc}) { id } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1", + "tokens": [ + { + "id": "tok-1" + }, + { + "id": "tok-2" + }, + { + "id": "tok-7" + } + ] + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-aggregate-count-exceeds-limit.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-aggregate-count-exceeds-limit.json new file mode 100644 index 0000000000..0996e18a43 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-aggregate-count-exceeds-limit.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity_aggregate { aggregate { count } nodes { id } } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity_aggregate": { + "aggregate": { + "count": 10 + }, + "nodes": [ + { + "id": "simple-1" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + }, + { + "id": "simple-5" + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-aggregate-enabled.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-aggregate-enabled.json new file mode 100644 index 0000000000..d201f4e150 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-aggregate-enabled.json @@ -0,0 +1,16 @@ +{ + "role": "public", + "request": { + "query": "{ User_aggregate { aggregate { count } } }" + }, + "status": 200, + "body": { + "data": { + "User_aggregate": { + "aggregate": { + "count": 6 + } + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-aggregate-not-enabled-table.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-aggregate-not-enabled-table.json new file mode 100644 index 0000000000..60c0e821ad --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-aggregate-not-enabled-table.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ Gravatar_aggregate { aggregate { count } } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "field 'Gravatar_aggregate' not found in type: 'query_root'", + "extensions": { + "path": "$.selectionSet.Gravatar_aggregate", + "code": "validation-failed" + } + } + ] + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-nested-aggregate-enabled.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-nested-aggregate-enabled.json new file mode 100644 index 0000000000..29f7503c32 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-public-nested-aggregate-enabled.json @@ -0,0 +1,29 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: {id: asc}, limit: 2) { id tokens_aggregate { aggregate { count } } } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user \"quoted\" 🚀", + "tokens_aggregate": { + "aggregate": { + "count": 1 + } + } + }, + { + "id": "user-1", + "tokens_aggregate": { + "aggregate": { + "count": 3 + } + } + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-raw-events-capped.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-raw-events-capped.json new file mode 100644 index 0000000000..6e60b6426f --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-raw-events-capped.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ raw_events(order_by: {serial: asc}) { serial } }" + }, + "status": 200, + "body": { + "data": { + "raw_events": [ + { + "serial": "1" + }, + { + "serial": "2" + }, + { + "serial": "3" + }, + { + "serial": "4" + }, + { + "serial": "5" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-caps-rows.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-caps-rows.json new file mode 100644 index 0000000000..691ee41af9 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-caps-rows.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-explicit-higher.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-explicit-higher.json new file mode 100644 index 0000000000..81ae6f2951 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-explicit-higher.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}, limit: 9) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + }, + { + "id": "simple-2" + }, + { + "id": "simple-3" + }, + { + "id": "simple-4" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-explicit-lower.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-explicit-lower.json new file mode 100644 index 0000000000..d7c4d79cff --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-explicit-lower.json @@ -0,0 +1,19 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}, limit: 2) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-1" + }, + { + "id": "simple-10" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-with-offset.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-with-offset.json new file mode 100644 index 0000000000..52aa3fff52 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/limits-response-limit-with-offset.json @@ -0,0 +1,22 @@ +{ + "role": "public", + "request": { + "query": "{ SimpleEntity(order_by: {id: asc}, offset: 7) { id } }" + }, + "status": 200, + "body": { + "data": { + "SimpleEntity": [ + { + "id": "simple-7" + }, + { + "id": "simple-8" + }, + { + "id": "simple-9" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/om-introspect-token-aggregate-order-by.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-introspect-token-aggregate-order-by.json new file mode 100644 index 0000000000..a30745427c --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-introspect-token-aggregate-order-by.json @@ -0,0 +1,92 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"Token_aggregate_order_by\") { inputFields { name type { name kind } } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "inputFields": [ + { + "name": "avg", + "type": { + "name": "Token_avg_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "count", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "max", + "type": { + "name": "Token_max_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "min", + "type": { + "name": "Token_min_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "stddev", + "type": { + "name": "Token_stddev_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "stddev_pop", + "type": { + "name": "Token_stddev_pop_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "stddev_samp", + "type": { + "name": "Token_stddev_samp_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "sum", + "type": { + "name": "Token_sum_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "var_pop", + "type": { + "name": "Token_var_pop_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "var_samp", + "type": { + "name": "Token_var_samp_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "variance", + "type": { + "name": "Token_variance_order_by", + "kind": "INPUT_OBJECT" + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/om-introspect-user-order-by.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-introspect-user-order-by.json new file mode 100644 index 0000000000..64e57b4280 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-introspect-user-order-by.json @@ -0,0 +1,64 @@ +{ + "role": "public", + "request": { + "query": "{ __type(name: \"User_order_by\") { inputFields { name type { name kind } } } }" + }, + "status": 200, + "body": { + "data": { + "__type": { + "inputFields": [ + { + "name": "accountType", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "address", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "gravatar", + "type": { + "name": "Gravatar_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "gravatar_id", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "id", + "type": { + "name": "order_by", + "kind": "ENUM" + } + }, + { + "name": "tokens_aggregate", + "type": { + "name": "Token_aggregate_order_by", + "kind": "INPUT_OBJECT" + } + }, + { + "name": "updatesCountOnUserForTesting", + "type": { + "name": "order_by", + "kind": "ENUM" + } + } + ] + } + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/om-order-array-rel-aggregate-count-desc.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-order-array-rel-aggregate-count-desc.json new file mode 100644 index 0000000000..b234755ca7 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-order-array-rel-aggregate-count-desc.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: [{tokens_aggregate: {count: desc}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-1" + }, + { + "id": "user-2" + }, + { + "id": "user-4" + }, + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-3" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/om-order-array-rel-aggregate-max.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-order-array-rel-aggregate-max.json new file mode 100644 index 0000000000..8e041497b2 --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-order-array-rel-aggregate-max.json @@ -0,0 +1,28 @@ +{ + "role": "public", + "request": { + "query": "{ User(order_by: [{tokens_aggregate: {max: {tokenId: desc}}}, {id: asc}]) { id } }" + }, + "status": 200, + "body": { + "data": { + "User": [ + { + "id": "user-dangling" + }, + { + "id": "user-4" + }, + { + "id": "user-2" + }, + { + "id": "user \"quoted\" 🚀" + }, + { + "id": "user-1" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/om-order-object-rel-nested-aggregate.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-order-object-rel-nested-aggregate.json new file mode 100644 index 0000000000..f028446b8d --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/om-order-object-rel-nested-aggregate.json @@ -0,0 +1,33 @@ +{ + "role": "public", + "request": { + "query": "{ Token(order_by: [{collection: {tokens_aggregate: {count: asc}}}, {id: asc}]) { id collection_id } }" + }, + "status": 200, + "body": { + "data": { + "Token": [ + { + "id": "tok-1", + "collection_id": "coll-1" + }, + { + "id": "tok-10", + "collection_id": "coll-1" + }, + { + "id": "tok-2", + "collection_id": "coll-1" + }, + { + "id": "tok-3", + "collection_id": "coll-1" + }, + { + "id": "tok-4", + "collection_id": "coll-2" + } + ] + } + } +} diff --git a/packages/e2e-tests/fixtures/differential/snapshots/limited/rm-aggregate-predicate-multi-column-count.json b/packages/e2e-tests/fixtures/differential/snapshots/limited/rm-aggregate-predicate-multi-column-count.json new file mode 100644 index 0000000000..7e46a4454e --- /dev/null +++ b/packages/e2e-tests/fixtures/differential/snapshots/limited/rm-aggregate-predicate-multi-column-count.json @@ -0,0 +1,18 @@ +{ + "role": "public", + "request": { + "query": "{ allRows: NftCollection(where: {tokens_aggregate: {count: {arguments: [owner_id, collection_id], distinct: false, predicate: {_gt: 0}}}}, order_by: {id: asc}) { id } distinctPairs: NftCollection(where: {tokens_aggregate: {count: {arguments: [owner_id, collection_id], distinct: true, predicate: {_gt: 1}}}}, order_by: {id: asc}) { id } }" + }, + "status": 200, + "body": { + "errors": [ + { + "message": "database query error", + "extensions": { + "path": "$", + "code": "unexpected" + } + } + ] + } +} diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 5005c54e56..cd769d3008 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -8,13 +8,19 @@ "test:templates": "vitest run src/template-tests/", "test:deps": "vitest run src/dependency-tests/", "test:e2e": "vitest run src/e2e/", + "test:differential": "vitest run --config vitest.differential.config.ts", + "record:differential": "tsx src/differential/record.ts", + "bench:differential": "tsx src/differential/bench.ts", + "soak:differential": "tsx src/differential/soakLoad.ts", "lint": "tsc --noEmit" }, "devDependencies": { "@types/node": "24.12.2", + "@types/ws": "^8.18.1", "envio": "file:../../packages/envio", "tsx": "^4.19.0", "typescript": "6.0.3", - "vitest": "4.1.0" + "vitest": "4.1.0", + "ws": "^8.21.0" } } diff --git a/packages/e2e-tests/soak-report.md b/packages/e2e-tests/soak-report.md new file mode 100644 index 0000000000..084ad498fc --- /dev/null +++ b/packages/e2e-tests/soak-report.md @@ -0,0 +1,34 @@ +# Soak load report + +Duration 57s, concurrency 24, target http://localhost:8081, 614 requests (10.9 req/s). + +## Status codes + +- 200: 614 (100.00%) + +Error rate (5xx + transport): **0.000%** + +## Latency + +Overall p50 474.6ms, p99 14837.3ms (n=614). + +| window | start (s) | requests | errors | p50 (ms) | p99 (ms) | +|---|---|---|---|---|---| +| 0 | 0 | 210 | 0 | 345.0 | 27927.3 | +| 1 | 8 | 57 | 0 | 696.4 | 11129.9 | +| 2 | 15 | 120 | 0 | 559.4 | 13691.8 | +| 3 | 23 | 76 | 0 | 713.6 | 25742.6 | +| 4 | 30 | 62 | 0 | 792.2 | 15141.0 | +| 5 | 38 | 89 | 0 | 472.7 | 13083.4 | + +p99 drift: window 1 (11129.9ms) -> window 5 (13083.4ms), x1.18 (threshold x2). + +## Resource usage (pid 29637) + +RSS: start 533MB, stabilized baseline 1381MB, final 1728MB, peak 1906MB, growth 25.1% (threshold 20%). +fd count: start 40, stabilized baseline 71, final 72, growth 1. + +## Result + +FAIL: +- RSS grew 25.1% from stabilized baseline (1381MB -> 1728MB), threshold 20%. diff --git a/packages/e2e-tests/src/differential/README.md b/packages/e2e-tests/src/differential/README.md new file mode 100644 index 0000000000..f14f55c830 --- /dev/null +++ b/packages/e2e-tests/src/differential/README.md @@ -0,0 +1,128 @@ +# Differential GraphQL suite + +Verifies that `envio serve` (the Rust GraphQL server) matches real Hasura +one-to-one, by running every corpus case against both engines and requiring +identical JSON responses — data, errors, and serialization alike. + +## Layout + +- `corpus/` — the query corpus, grouped by category. Each case runs as a + given role (`public` = no auth headers, `admin` = admin secret) in one or + more phases (`default` = production defaults; `limited` = response limit 5 + plus aggregates enabled for a few tables). +- `fixtureModel.ts` — the tracked tables and relationships of the fixture, + mirroring exactly what `Hasura.res` `trackDatabase` derives from + `scenarios/test_codegen/schema.graphql`. +- `hasuraSetup.ts` — replays the same metadata API calls the indexer makes + at init (clear → reload → pg_track_tables → select permissions → + relationships), parameterized by phase. +- `../../fixtures/differential/schema.sql` — DDL dump of the schema + `envio local db-migrate setup` creates for scenarios/test_codegen. +- `../../fixtures/differential/seed.sql` — deterministic rows exercising + serialization edge cases. +- `../../fixtures/differential/snapshots/` — recorded Hasura responses; the + ground-truth oracle, regenerated with `pnpm record:differential`. + +## Running + +**Fast loop (Rust iteration — no Hasura/Docker needed):** the oracle +snapshots under `fixtures/differential/snapshots/` are the correctness +ground truth. Start `envio serve` against the small fixture dataset +(`schema.sql` + `seed.sql`, no `bench-seed.sql`) and diff: + +```sh +cd scenarios/test_codegen && pnpm exec envio serve --port 8081 & +cd packages/e2e-tests && pnpm exec tsx src/differential/diffServe.ts +``` + +This runs the ~590 default-phase cases concurrently in a few seconds +against the already-recorded snapshots — nothing needs live Hasura. Use +`--phase limited` (with serve restarted under +`ENVIO_HASURA_RESPONSE_LIMIT=5 ENVIO_HASURA_PUBLIC_AGGREGATE='["User","Token","SimpleEntity","raw_events","_meta"]'`) +for the limited-phase cases, and `--filter ` / `--verbose N` to +narrow down a failure. + +**Full suite (needs Postgres 5433 + Hasura 8080 live — CI runs this):** + +```sh +pnpm --filter e2e-tests record:differential # refresh Hasura oracle snapshots +pnpm --filter e2e-tests test:differential # diff Hasura vs envio serve, both engines live +``` + +`test:differential` spawns `envio serve` itself and drives every HTTP case +plus the WebSocket subscription scenarios (`subscriptions.test.ts`) +against a live Hasura container — the authoritative check before landing +a change, but slower (~5 min) since every case is a live round trip to +both engines. Prefer `diffServe.ts` for iteration; run this before a PR. + +### Benchmarking + +Also needs Hasura only once — see `bench.ts`'s module doc comment. In +short: `--record-baseline` captures Hasura's per-case timing + resource +usage to `fixtures/differential/hasura-baseline.json` (committed; re-run +after a real perf-relevant Postgres/dataset change, not after every Rust +edit); the default mode benchmarks only `envio serve` against that stored +baseline, so Hasura/Docker can stay stopped while iterating on Rust. +`bench.ts` measures timing only — always confirm correctness with +`diffServe.ts` on the small dataset separately. + +### Soak / load testing + +`bench.ts` is single-connection (concurrency 1) latency only. `soakLoad.ts` +fires a mixed sample of the `bench: true` corpus at N concurrent workers +against a running `envio serve` for an extended duration, and checks the +things that only show up under sustained concurrent load: RSS growth +(leak), fd-count growth (leak), p99 latency drift over time, and zero 5xx +responses. Needs `envio serve` already running (or pass `--spawn`) — no +Hasura needed. + +```sh +cd scenarios/test_codegen && pnpm exec envio serve --port 8081 & +cd packages/e2e-tests +pnpm soak:differential -- --duration 60s --concurrency 32 # quick local iteration +pnpm soak:differential -- --duration 2h --concurrency 48 --spawn # real acceptance soak +``` + +Exits non-zero (and prints why) on any 5xx, an RSS or fd-count growth +trend past a configurable threshold (excluding an initial warmup slice), +or late-run p99 more than `--p99-drift-multiplier` (default 2x) worse than +an early stabilized window. See the flag list in `soakLoad.ts`'s module +doc comment for the full set of thresholds/knobs. + +## Needs a live-Hasura re-record + +Fixture/schema changes invalidate ALL recorded snapshots (including +introspection), so the items below batch into one re-record session against +live Hasura v2.43 (`pnpm record:differential` after the fixture edits): + +- **`column_name_format: snake_case` fixture coverage** — serve supports the + snake_case column-name mode but the fixture only exercises the default + camelCase naming; add a snake_case-configured schema variant and corpus + cases so naming-mode parity is snapshot-verified. +- **`envio_effect_*` table in the fixture** — effect-cache tables get a + public/admin visibility split distinct from entity tables; add one to + `schema.sql` and record corpus cases for both roles to pin that split. +- **Byte-level (non-JSON-normalized) snapshot recording** — snapshots are + stored as re-serialized parsed JSON, which hides float-formatting + differences (e.g. `1.0` vs `1`); record raw response bytes alongside so + float-formatting parity is verifiable. +- **GET /v1/graphql corpus cases** — Hasura answers plain GET (GraphiQL / + query-over-GET) while serve currently 400s without upgrade headers; record + Hasura's GET behavior so the intended parity target is pinned. +- **Auth-matrix corpus cases** — only public/admin/admin-wrong are covered; + record combinations of `X-Hasura-Role` with and without a valid admin + secret (and unknown roles) to pin the full role-resolution matrix. + +## Regenerating the fixture schema + +When the generated DDL changes (packages/envio/src/db/*), re-run: + +```sh +cd scenarios/test_codegen && pnpm db-setup +PGPASSWORD=testing pg_dump -h localhost -p 5433 -U postgres -d envio-dev \ + --schema-only --schema=public --no-owner --no-privileges > /tmp/dump.sql +``` + +then clean it into `fixtures/differential/schema.sql` (drop psql +`\restrict` directives, `SET` statements, and the `CREATE SCHEMA public` +line — keep the header comment and the DROP/CREATE SCHEMA prelude). diff --git a/packages/e2e-tests/src/differential/bench.ts b/packages/e2e-tests/src/differential/bench.ts new file mode 100644 index 0000000000..8fd012c1c1 --- /dev/null +++ b/packages/e2e-tests/src/differential/bench.ts @@ -0,0 +1,529 @@ +/** + * Per-case benchmark: Hasura vs envio serve on identical data, plus + * process-level resource usage. + * + * This measures TIMING ONLY. Correctness is diffServe.ts's job, checked + * against the small fixture dataset (schema.sql + seed.sql) — this script + * runs against whatever dataset is currently loaded, typically the much + * larger bench-seed.sql, so it must NOT also diff against the (small- + * dataset) oracle snapshots: unfiltered list queries would spuriously + * "mismatch" simply because bench-seed.sql added rows. + * + * Two modes, so Rust iteration never needs Hasura/Docker running: + * + * --record-baseline Runs ONLY against Hasura (must be up), captures + * per-case latency stats + Hasura/Postgres resource + * usage, writes fixtures/differential/hasura-baseline.json. + * Run this once per dataset change (e.g. after + * re-seeding bench-seed.sql); Hasura's numbers don't + * change between Rust rebuilds. A --filter'd re-record + * merges into the existing file instead of replacing + * it, so fixing one case's expected behavior doesn't + * discard timings for every other case. + * + * (default) Runs ONLY against envio serve (must be up) and + * computes speedup against the stored baseline — no + * live Hasura needed. + * + * Methodology: + * - Sampling is time-budgeted: each case runs until min-iters samples are + * collected and either the per-case budget is spent or max-iters is hit. + * Fast cases get many samples cheaply; slow full-table scans stop early + * (their variance is low anyway). + * - Default concurrency is 1. Cases CAN run on a worker pool + * (--concurrency N) for a faster sweep, but per-case numbers get noisy: + * the baseline and engine-only runs happen in separate processes at + * separate times, so "N cases running concurrently" means a different + * MIX of light/heavy queries contends for the one shared Postgres + * instance in each run. Verified empirically: cases that looked "2-4x + * slower" at --concurrency 6 were actually 1.4-3.8x FASTER when + * re-measured at --concurrency 1 — the geomean speedup stayed directionally + * right, but individual "which cases regressed" conclusions from a + * concurrent sweep are not reliable. Use --concurrency >1 only for a + * quick smoke check ("is anything catastrophically slower"), and + * --concurrency 1 (the default) for the numbers that go in a report or + * drive an optimization decision. + * - Resource usage is sampled from /proc every 500ms for the relevant + * process tree (Hasura container or envio serve) and for Postgres. + * + * Usage: + * pnpm --filter e2e-tests exec tsx src/differential/bench.ts --record-baseline [--seed] + * pnpm --filter e2e-tests exec tsx src/differential/bench.ts + * [--all] [--filter substr] [--concurrency N] [--budget-ms N] + * [--min-iters N] [--max-iters N] + */ + +import { execSync } from "node:child_process"; +import { readFile, writeFile } from "node:fs/promises"; +import { readFileSync, readdirSync } from "node:fs"; +import { allCases } from "./corpus/index.js"; +import { hasuraUrl, serveUrl } from "./env.js"; +import { runCase } from "./runner.js"; +import { runSql } from "./hasuraSetup.js"; +import { arg, flag } from "./cliArgs.js"; +import type { CorpusCase } from "./corpus.js"; + +const concurrency = Number(arg("--concurrency") ?? 1); +const budgetMs = Number(arg("--budget-ms") ?? 1500); +const minIters = Number(arg("--min-iters") ?? 3); +const maxIters = Number(arg("--max-iters") ?? 30); +const warmupRounds = Number(arg("--warmup") ?? 2); +const filter = arg("--filter"); +const recordBaseline = flag("--record-baseline"); + +const baselinePath = new URL( + "../../fixtures/differential/hasura-baseline.json", + import.meta.url +); + +interface Stats { + p50: number; + p90: number; + mean: number; + min: number; + n: number; +} + +function stats(samplesMs: number[]): Stats { + const s = [...samplesMs].sort((a, b) => a - b); + const pick = (q: number) => s[Math.min(s.length - 1, Math.floor(q * s.length))]!; + return { + p50: pick(0.5), + p90: pick(0.9), + mean: s.reduce((a, b) => a + b, 0) / s.length, + min: s[0]!, + n: s.length, + }; +} + +async function timed(endpoint: string, corpusCase: CorpusCase): Promise { + const t0 = performance.now(); + await runCase(endpoint, corpusCase); + return performance.now() - t0; +} + +async function benchOne( + endpoint: string, + corpusCase: CorpusCase +): Promise { + await runCase(endpoint, corpusCase); // untimed correctness/warm hit + for (let i = 0; i < warmupRounds; i++) { + await timed(endpoint, corpusCase); + } + const samples: number[] = []; + const started = performance.now(); + while (true) { + samples.push(await timed(endpoint, corpusCase)); + const elapsed = performance.now() - started; + if (samples.length >= maxIters) break; + if (samples.length >= minIters && elapsed > budgetMs) break; + } + return stats(samples); +} + +// --------------------------------------------------------------------------- +// /proc resource sampling + +interface ProcSnapshot { + cpuTicks: number; + rssKb: number; +} + +function snapshotPids(pids: number[]): ProcSnapshot { + let cpuTicks = 0; + let rssKb = 0; + for (const pid of pids) { + try { + const stat = readFileSync(`/proc/${pid}/stat`, "utf8"); + // utime and stime are fields 14 and 15 (1-indexed), after the comm + // field which may contain spaces — split after the closing paren. + const after = stat.slice(stat.lastIndexOf(")") + 2).split(" "); + cpuTicks += Number(after[11]) + Number(after[12]); + const status = readFileSync(`/proc/${pid}/status`, "utf8"); + const m = status.match(/VmRSS:\s+(\d+) kB/); + if (m) rssKb += Number(m[1]); + } catch { + // process exited between listing and reading + } + } + return { cpuTicks, rssKb }; +} + +function descendantsOf(rootPids: number[]): number[] { + const byParent = new Map(); + for (const entry of readdirSync("/proc")) { + if (!/^\d+$/.test(entry)) continue; + try { + const stat = readFileSync(`/proc/${entry}/stat`, "utf8"); + const after = stat.slice(stat.lastIndexOf(")") + 2).split(" "); + const ppid = Number(after[1]); + const list = byParent.get(ppid) ?? []; + list.push(Number(entry)); + byParent.set(ppid, list); + } catch { + // raced + } + } + const all = new Set(rootPids); + const queue = [...rootPids]; + while (queue.length) { + for (const child of byParent.get(queue.shift()!) ?? []) { + if (!all.has(child)) { + all.add(child); + queue.push(child); + } + } + } + return [...all]; +} + +function pidsByCommand(pattern: string): number[] { + try { + return execSync(`pgrep -f ${JSON.stringify(pattern)}`, { encoding: "utf8" }) + .trim() + .split("\n") + .filter(Boolean) + .map(Number); + } catch { + return []; + } +} + +function postgresPids(): number[] { + const pids: number[] = []; + for (const entry of readdirSync("/proc")) { + if (!/^\d+$/.test(entry)) continue; + try { + const comm = readFileSync(`/proc/${entry}/comm`, "utf8").trim(); + if (comm === "postgres") pids.push(Number(entry)); + } catch { + // raced + } + } + return pids; +} + +function hasuraContainerPid(): number[] { + for (const name of ["hasura-test", "envio-hasura"]) { + try { + const pid = Number( + execSync(`docker inspect -f '{{.State.Pid}}' ${name} 2>/dev/null`, { + encoding: "utf8", + }).trim() + ); + if (pid > 0) return [pid]; + } catch { + // try next name + } + } + return []; +} + +interface ResourceReport { + label: string; + cpuSeconds: number; + peakRssMb: number; + avgRssMb: number; +} + +class ResourceSampler { + private tracks: { + label: string; + pids: () => number[]; + startCpu: number; + lastCpu: number; + peakRssKb: number; + rssSamples: number[]; + }[] = []; + private timer?: NodeJS.Timeout; + private clockTicks = 100; + + constructor(specs: { label: string; pids: () => number[] }[]) { + try { + this.clockTicks = Number( + execSync("getconf CLK_TCK", { encoding: "utf8" }).trim() + ); + } catch { + // default 100 + } + for (const spec of specs) { + const snap = snapshotPids(spec.pids()); + this.tracks.push({ + label: spec.label, + pids: spec.pids, + startCpu: snap.cpuTicks, + lastCpu: snap.cpuTicks, + peakRssKb: snap.rssKb, + rssSamples: snap.rssKb ? [snap.rssKb] : [], + }); + } + } + + start() { + this.timer = setInterval(() => { + for (const t of this.tracks) { + const snap = snapshotPids(t.pids()); + t.lastCpu = snap.cpuTicks; + if (snap.rssKb > 0) { + t.peakRssKb = Math.max(t.peakRssKb, snap.rssKb); + t.rssSamples.push(snap.rssKb); + } + } + }, 500); + this.timer.unref(); + } + + stop(): ResourceReport[] { + if (this.timer) clearInterval(this.timer); + return this.tracks.map((t) => ({ + label: t.label, + cpuSeconds: (t.lastCpu - t.startCpu) / this.clockTicks, + peakRssMb: t.peakRssKb / 1024, + avgRssMb: + t.rssSamples.length === 0 + ? 0 + : t.rssSamples.reduce((a, b) => a + b, 0) / t.rssSamples.length / 1024, + })); + } +} + +// --------------------------------------------------------------------------- + +function selectCases(): CorpusCase[] { + return allCases.filter( + (c) => + (c.phases ?? ["default"]).includes("default") && + (flag("--all") ? c.compare !== "rootSet" : c.bench === true) && + (!filter || c.name.includes(filter)) + ); +} + +async function runPool( + items: T[], + worker: (item: T) => Promise +): Promise { + let next = 0; + await Promise.all( + Array.from({ length: Math.max(1, concurrency) }, async () => { + while (next < items.length) { + await worker(items[next++]!); + } + }) + ); +} + +interface Baseline { + recordedAt: string; + cases: Record; + resources: ResourceReport[]; +} + +async function recordBaselineMode() { + if (flag("--seed")) { + console.log("Applying bench-seed.sql (large volume)..."); + const sql = await readFile( + new URL("../../fixtures/differential/bench-seed.sql", import.meta.url), + "utf8" + ); + await runSql(sql); + console.log("Seeded."); + } + + const cases = selectCases(); + console.log( + `Recording Hasura baseline for ${cases.length} cases (budget ${budgetMs}ms/case, ${minIters}-${maxIters} iters, concurrency ${concurrency})\n` + ); + console.log( + "This is the only step that needs Hasura/Docker running — the result is\n" + + "cached to disk so Rust iteration never has to start Hasura again.\n" + ); + + const sampler = new ResourceSampler([ + { label: "hasura", pids: () => descendantsOf(hasuraContainerPid()) }, + { label: "postgres", pids: postgresPids }, + ]); + sampler.start(); + + // Merge into any existing baseline so a filtered re-record (e.g. after + // fixing one case) doesn't discard timings for every other case. + let existing: Baseline | undefined; + try { + existing = JSON.parse(await readFile(baselinePath, "utf8")) as Baseline; + } catch { + existing = undefined; + } + const results: Record = { ...(existing?.cases ?? {}) }; + await runPool(cases, async (c) => { + const s = await benchOne(hasuraUrl, c); + results[c.name] = s; + console.log(`${c.name.padEnd(52)} hasura p50 ${s.p50.toFixed(1).padStart(8)}ms (n=${s.n})`); + }); + + const resources = sampler.stop(); + console.log("\nHasura resource usage during recording:"); + for (const r of resources) { + console.log( + ` ${r.label.padEnd(12)} cpu ${r.cpuSeconds.toFixed(1)}s | peak rss ${r.peakRssMb.toFixed(0)} MB | avg rss ${r.avgRssMb.toFixed(0)} MB` + ); + } + + // Resource usage reflects only the cases just recorded, so only replace + // the stored figures on a broad (unfiltered) run; a targeted --filter + // re-record keeps the prior full-sweep numbers. + const baseline: Baseline = { + recordedAt: new Date().toISOString(), + cases: results, + resources: filter && existing ? existing.resources : resources, + }; + + await writeFile(baselinePath, JSON.stringify(baseline, null, 1) + "\n"); + console.log(`\nBaseline written to ${baselinePath.pathname}`); + console.log( + "You can now stop Hasura/Docker and iterate with:\n" + + " pnpm --filter e2e-tests exec tsx src/differential/bench.ts" + ); +} + +async function engineMode() { + let baseline: Baseline; + try { + baseline = JSON.parse(await readFile(baselinePath, "utf8")) as Baseline; + } catch { + console.error( + `No baseline found at ${baselinePath.pathname}.\n` + + "Start Hasura once and run:\n" + + " pnpm --filter e2e-tests exec tsx src/differential/bench.ts --record-baseline" + ); + process.exit(1); + } + + const cases = selectCases(); + console.log( + `Benchmarking envio serve for ${cases.length} cases against the recorded Hasura baseline\n` + + `(from ${baseline.recordedAt}) — no live Hasura needed.\n` + + "NOTE: this measures TIMING ONLY, against whatever dataset is currently\n" + + "loaded (e.g. after bench-seed.sql). Correctness is a separate concern —\n" + + "verify with diffServe.ts against the small fixture dataset (schema.sql +\n" + + "seed.sql, no bench-seed.sql) BEFORE re-seeding for a benchmark run.\n" + ); + + const servePids = pidsByCommand("bin\\.mjs serve"); + const sampler = new ResourceSampler([ + { label: "envio serve", pids: () => descendantsOf(servePids) }, + { label: "postgres", pids: postgresPids }, + ]); + sampler.start(); + const sweepStart = performance.now(); + + interface CaseResult { + name: string; + envio: Stats; + hasura: Stats | undefined; + speedup: number | undefined; + } + const results: CaseResult[] = []; + + await runPool(cases, async (c) => { + const envio = await benchOne(serveUrl, c); + const hasura = baseline.cases[c.name]; + const speedup = hasura ? hasura.p50 / envio.p50 : undefined; + results.push({ name: c.name, envio, hasura, speedup }); + console.log( + `${c.name.padEnd(52)} envio p50 ${envio.p50.toFixed(1).padStart(8)}ms` + + (hasura + ? ` | hasura(baseline) p50 ${hasura.p50.toFixed(1).padStart(8)}ms | x${speedup!.toFixed(2)}` + : " | (no baseline)") + ); + }); + + const sweepSeconds = (performance.now() - sweepStart) / 1000; + const resources = sampler.stop(); + + results.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)); + const withSpeedup = results.filter((r) => r.speedup !== undefined); + const geomean = withSpeedup.length + ? Math.exp( + withSpeedup.reduce((a, r) => a + Math.log(r.speedup!), 0) / + withSpeedup.length + ) + : undefined; + const slower = withSpeedup.filter((r) => r.speedup! < 0.95); + const missingBaseline = results.filter((r) => r.hasura === undefined); + + console.log(`\nSweep took ${sweepSeconds.toFixed(0)}s`); + if (geomean !== undefined) { + console.log( + `Geometric-mean speedup (p50, envio vs recorded hasura baseline): x${geomean.toFixed(2)}` + ); + } + console.log(`Cases where envio serve is >5% slower than baseline: ${slower.length}`); + for (const r of slower) { + console.log( + ` ${r.name}: hasura(baseline) ${r.hasura!.p50.toFixed(1)}ms vs envio ${r.envio.p50.toFixed(1)}ms` + ); + } + if (missingBaseline.length > 0) { + console.log( + `Cases with no recorded baseline (re-run --record-baseline to cover them): ${missingBaseline.map((r) => r.name).join(", ")}` + ); + } + console.log("\nResource usage over the sweep:"); + for (const r of resources) { + console.log( + ` ${r.label.padEnd(20)} cpu ${r.cpuSeconds.toFixed(1)}s | peak rss ${r.peakRssMb.toFixed(0)} MB | avg rss ${r.avgRssMb.toFixed(0)} MB` + ); + } + + const report = [ + `# Differential benchmark — Hasura (recorded baseline) vs envio serve`, + ``, + `Baseline recorded ${baseline.recordedAt}. ${cases.length} cases; per-case budget ${budgetMs}ms, ${minIters}-${maxIters} iterations, warmup ${warmupRounds}; case concurrency ${concurrency}; sweep ${sweepSeconds.toFixed(0)}s.`, + ``, + `## Resources (envio serve, this sweep)`, + ``, + `| process | cpu seconds | peak rss (MB) | avg rss (MB) |`, + `|---|---|---|---|`, + ...resources.map( + (r) => + `| ${r.label} | ${r.cpuSeconds.toFixed(1)} | ${r.peakRssMb.toFixed(0)} | ${r.avgRssMb.toFixed(0)} |` + ), + ``, + `## Resources (hasura, at baseline recording time)`, + ``, + `| process | cpu seconds | peak rss (MB) | avg rss (MB) |`, + `|---|---|---|---|`, + ...baseline.resources.map( + (r) => + `| ${r.label} | ${r.cpuSeconds.toFixed(1)} | ${r.peakRssMb.toFixed(0)} | ${r.avgRssMb.toFixed(0)} |` + ), + ``, + `## Per case`, + ``, + `| case | hasura p50 (ms, baseline) | envio p50 (ms) | envio p90 | speedup (p50) | samples |`, + `|---|---|---|---|---|---|`, + ...results.map( + (r) => + `| ${r.name} | ${r.hasura ? r.hasura.p50.toFixed(1) : "-"} | ${r.envio.p50.toFixed(1)} | ${r.envio.p90.toFixed(1)} | ${r.speedup ? `x${r.speedup.toFixed(2)}` : "-"} | ${r.envio.n} |` + ), + ``, + geomean !== undefined + ? `Geometric-mean p50 speedup vs baseline: **x${geomean.toFixed(2)}**; cases >5% slower: **${slower.length}**.` + : "", + ].join("\n"); + const out = new URL("../../bench-report.md", import.meta.url); + await writeFile(out, report + "\n"); + console.log(`\nReport written to ${out.pathname}`); +} + +async function main() { + if (recordBaseline) { + await recordBaselineMode(); + } else { + await engineMode(); + } +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/packages/e2e-tests/src/differential/cliArgs.ts b/packages/e2e-tests/src/differential/cliArgs.ts new file mode 100644 index 0000000000..c9a4e32c1a --- /dev/null +++ b/packages/e2e-tests/src/differential/cliArgs.ts @@ -0,0 +1,15 @@ +/** + * Minimal `--flag` / `--name value` CLI argument parsing shared by the + * differential scripts, so each script doesn't slice/index process.argv + * itself. + */ +const argv = process.argv.slice(2); + +export function arg(name: string): string | undefined { + const i = argv.indexOf(name); + return i >= 0 ? argv[i + 1] : undefined; +} + +export function flag(name: string): boolean { + return argv.includes(name); +} diff --git a/packages/e2e-tests/src/differential/corpus.ts b/packages/e2e-tests/src/differential/corpus.ts new file mode 100644 index 0000000000..6ea819a1c4 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus.ts @@ -0,0 +1,88 @@ +/** + * Corpus case definitions for the differential GraphQL suite. + * + * Every case is executed against both real Hasura and `envio serve`; the + * full JSON response bodies (data and errors alike) must be identical. + */ + +// "admin-wrong" sends an incorrect admin secret — pins Hasura's +// access-denied error shape (HTTP 200, not 401; verified live). +export type Role = "admin" | "public" | "admin-wrong"; + +/** + * default — Hasura tracked with no response limit and no aggregate entities + * (production defaults: ENVIO_HASURA_RESPONSE_LIMIT unset, + * ENVIO_HASURA_PUBLIC_AGGREGATE=[]). + * limited — response limit 5; aggregates enabled for User, Token, + * SimpleEntity, raw_events and _meta. + */ +export type Phase = "default" | "limited"; + +export const phaseConfigs: Record< + Phase, + { responseLimit?: number; aggregateEntities: string[] } +> = { + default: { aggregateEntities: [] }, + limited: { + responseLimit: 5, + aggregateEntities: ["User", "Token", "SimpleEntity", "raw_events", "_meta"], + }, +}; + +export interface CorpusCase { + /** Unique within the whole corpus; used for snapshot file names. */ + name: string; + query: string; + variables?: Record; + /** Raw JSON object text for variables that JavaScript cannot represent + * losslessly (for example 1e400). Mutually exclusive with `variables`. */ + rawVariables?: string; + operationName?: string; + /** Defaults to "public" — the role of unauthenticated requests. */ + role?: Role; + /** Phases the case runs in. Defaults to ["default"]. */ + phases?: Phase[]; + /** + * exact — response bodies must be byte-for-byte equal as parsed JSON. + * rootSet — arrays directly under data.* are compared as multisets + * (for queries without a deterministic order_by). + */ + compare?: "exact" | "rootSet"; + /** Include in the performance benchmark suite. */ + bench?: boolean; +} + +export interface SubscriptionStep { + /** SQL to run (as admin, via Hasura run_sql) after the previous payload. */ + sql?: string; + /** Roughly how many payloads to await after this step. */ + expectPayloads: number; +} + +export interface SubscriptionCase { + name: string; + query: string; + variables?: Record; + role?: Role; + phases?: Phase[]; + /** + * Which WebSocket subprotocol to use: + * graphql-transport-ws — the modern graphql-ws protocol. + * graphql-ws — the legacy subscriptions-transport-ws protocol. + */ + protocol: "graphql-transport-ws" | "graphql-ws"; + steps: SubscriptionStep[]; +} + +const seen = new Set(); + +export function defineCases(cases: CorpusCase[]): CorpusCase[] { + for (const c of cases) { + if (seen.has(c.name)) throw new Error(`Duplicate corpus case: ${c.name}`); + if (c.variables !== undefined && c.rawVariables !== undefined) { + throw new Error(`Corpus case ${c.name} defines variables twice`); + } + seen.add(c.name); + } + return cases; +} diff --git a/packages/e2e-tests/src/differential/corpus/01-basic.ts b/packages/e2e-tests/src/differential/corpus/01-basic.ts new file mode 100644 index 0000000000..757260f162 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/01-basic.ts @@ -0,0 +1,113 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "basic-select-all-users", + query: `{ User(order_by: {id: asc}) { id address gravatar_id updatesCountOnUserForTesting accountType } }`, + bench: true, + }, + { + name: "basic-select-no-order", + query: `{ SimpleEntity { id value } }`, + compare: "rootSet", + }, + { + name: "basic-by-pk-hit", + query: `{ User_by_pk(id: "user-1") { id address accountType } }`, + bench: true, + }, + { + name: "basic-by-pk-miss", + query: `{ User_by_pk(id: "nope") { id } }`, + }, + { + name: "basic-by-pk-special-chars", + query: `{ User_by_pk(id: "user \\"quoted\\" 🚀") { id address } }`, + }, + { + name: "basic-typename-root", + query: `{ __typename User(order_by: {id: asc}, limit: 1) { __typename id } }`, + }, + { + name: "basic-typename-by-pk", + query: `{ User_by_pk(id: "user-1") { __typename } }`, + }, + { + name: "basic-aliases", + query: `{ renamed: User(order_by: {id: asc}, limit: 2) { theId: id addr: address t: __typename } }`, + }, + { + name: "basic-same-field-twice", + query: `{ User(order_by: {id: asc}, limit: 1) { id id address address } }`, + }, + { + name: "basic-alias-two-roots-same-table", + query: `{ first: User(order_by: {id: asc}, limit: 1) { id } last: User(order_by: {id: desc}, limit: 1) { id } }`, + }, + { + name: "basic-multiple-root-fields", + query: `{ User(order_by: {id: asc}) { id } Gravatar(order_by: {id: asc}) { id } Token(order_by: {id: asc}, limit: 3) { id } }`, + }, + { + name: "basic-fragment-spread", + query: `fragment UserFields on User { id address accountType } { User(order_by: {id: asc}, limit: 2) { ...UserFields } }`, + }, + { + name: "basic-inline-fragment", + query: `{ User(order_by: {id: asc}, limit: 2) { ... on User { id accountType } } }`, + }, + { + name: "basic-nested-fragments", + query: `fragment A1 on User { id ...B1 } fragment B1 on User { address } { User(order_by: {id: asc}, limit: 1) { ...A1 } }`, + }, + { + name: "basic-variables-string", + query: `query ($id: String!) { User_by_pk(id: $id) { id address } }`, + variables: { id: "user-2" }, + }, + { + name: "basic-variables-default-value", + query: `query ($lim: Int = 2) { User(order_by: {id: asc}, limit: $lim) { id } }`, + }, + { + name: "basic-variables-null-optional", + query: `query ($lim: Int) { User(order_by: {id: asc}, limit: $lim) { id } }`, + variables: { lim: null }, + }, + { + name: "basic-operation-name-selection", + query: `query GetUsers { User(order_by: {id: asc}, limit: 1) { id } } query GetGravatars { Gravatar(order_by: {id: asc}, limit: 1) { id } }`, + operationName: "GetGravatars", + }, + { + name: "basic-named-operation", + query: `query Q { SimpleEntity(order_by: {id: asc}, limit: 1) { id value } }`, + }, + { + name: "basic-skip-include", + query: `query ($withAddr: Boolean!, $skipType: Boolean!) { User(order_by: {id: asc}, limit: 2) { id address @include(if: $withAddr) accountType @skip(if: $skipType) } }`, + variables: { withAddr: true, skipType: true }, + }, + { + name: "basic-skip-include-false", + query: `query ($withAddr: Boolean!, $skipType: Boolean!) { User(order_by: {id: asc}, limit: 2) { id address @include(if: $withAddr) accountType @skip(if: $skipType) } }`, + variables: { withAddr: false, skipType: false }, + }, + { + name: "basic-empty-table", + query: `{ CustomSelectionTestPass(where: {id: {_eq: "missing"}}) { id } }`, + }, + { + name: "basic-63-char-table", + query: `{ EntityWith63LenghtName______________________________________one(order_by: {id: asc}) { id } }`, + }, + { + name: "basic-restricted-field-name", + query: `{ EntityWithRestrictedReScriptField(order_by: {id: asc}) { id type } }`, + }, + { + name: "basic-admin-role", + role: "admin", + query: `{ User(order_by: {id: asc}) { id address } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/02-where.ts b/packages/e2e-tests/src/differential/corpus/02-where.ts new file mode 100644 index 0000000000..b1ea4c8b8c --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/02-where.ts @@ -0,0 +1,218 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "where-string-eq", + query: `{ SimpleEntity(where: {value: {_eq: "v3"}}, order_by: {id: asc}) { id value } }`, + bench: true, + }, + { + name: "where-string-neq", + query: `{ SimpleEntity(where: {value: {_neq: "v3"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-string-in", + query: `{ SimpleEntity(where: {id: {_in: ["simple-1", "simple-3", "missing"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-string-in-empty", + query: `{ SimpleEntity(where: {id: {_in: []}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-string-nin", + query: `{ SimpleEntity(where: {id: {_nin: ["simple-1", "simple-2"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-string-gt-lt", + query: `{ SimpleEntity(where: {id: {_gt: "simple-2", _lt: "simple-5"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-string-gte-lte", + query: `{ SimpleEntity(where: {id: {_gte: "simple-2", _lte: "simple-5"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-like", + query: `{ User(where: {address: {_like: "%000001"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-nlike", + query: `{ User(where: {address: {_nlike: "%000001"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-ilike", + query: `{ User(where: {address: {_ilike: "0XAAAA%"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-nilike", + query: `{ User(where: {address: {_nilike: "0XAAAA%02"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-similar", + query: `{ SimpleEntity(where: {value: {_similar: "v(1|2)"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-nsimilar", + query: `{ SimpleEntity(where: {value: {_nsimilar: "v(1|2)"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-regex", + query: `{ SimpleEntity(where: {value: {_regex: "^v[13]$"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-iregex", + query: `{ SimpleEntity(where: {value: {_iregex: "^V[13]$"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-niregex", + query: `{ SimpleEntity(where: {value: {_niregex: "^V[13]$"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-like-escape-chars", + query: `{ EntityWithAllNonArrayTypes(where: {string: {_like: "%\\"double\\"%"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-is-null-true", + query: `{ User(where: {gravatar_id: {_is_null: true}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-is-null-false", + query: `{ User(where: {gravatar_id: {_is_null: false}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-int-comparisons", + query: `{ User(where: {updatesCountOnUserForTesting: {_gte: 0, _lt: 100}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } }`, + }, + { + name: "where-int-negative", + query: `{ User(where: {updatesCountOnUserForTesting: {_lt: 0}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } }`, + }, + { + name: "where-numeric-eq-string-literal", + query: `{ Token(where: {tokenId: {_eq: "1000000000000000000000000000000"}}, order_by: {id: asc}) { id tokenId } }`, + }, + { + name: "where-numeric-eq-int-literal", + query: `{ Token(where: {tokenId: {_eq: 1}}, order_by: {id: asc}) { id tokenId } }`, + }, + { + name: "where-numeric-gt-huge", + query: `{ Token(where: {tokenId: {_gt: "99999999999999999999999999999"}}, order_by: {id: asc}) { id tokenId } }`, + }, + { + name: "where-numeric-in-mixed", + query: `{ Token(where: {tokenId: {_in: [0, "8", 10]}}, order_by: {id: asc}) { id tokenId } }`, + }, + { + name: "where-numeric-negative", + query: `{ Token(where: {tokenId: {_lt: 0}}, order_by: {id: asc}) { id tokenId } }`, + }, + { + name: "where-float-eq", + query: `{ EntityWithAllNonArrayTypes(where: {float_: {_eq: "3.14159"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-float-gt", + query: `{ EntityWithAllNonArrayTypes(where: {float_: {_gt: 0}}, order_by: {id: asc}) { id float_ } }`, + }, + { + name: "where-bool-eq", + query: `{ EntityWithAllNonArrayTypes(where: {bool: {_eq: true}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-enum-eq", + query: `{ User(where: {accountType: {_eq: "ADMIN"}}, order_by: {id: asc}) { id accountType } }`, + }, + { + name: "where-enum-in", + query: `{ User(where: {accountType: {_in: ["ADMIN", "USER"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-enum-neq", + query: `{ Gravatar(where: {size: {_neq: "SMALL"}}, order_by: {id: asc}) { id size } }`, + }, + { + name: "where-timestamp-eq", + query: `{ EntityWithTimestamp(where: {timestamp: {_eq: "2024-01-15T12:34:56.123456+00:00"}}, order_by: {id: asc}) { id timestamp } }`, + }, + { + name: "where-timestamp-range", + query: `{ EntityWithTimestamp(where: {timestamp: {_gte: "1970-01-01", _lt: "2025-01-01"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-timestamp-zoned-literal", + query: `{ EntityWithTimestamp(where: {timestamp: {_eq: "2024-06-15T12:00:00+09:30"}}, order_by: {id: asc}) { id timestamp } }`, + }, + { + name: "where-and-implicit", + query: `{ User(where: {accountType: {_eq: "USER"}, gravatar_id: {_is_null: false}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-and-explicit", + query: `{ User(where: {_and: [{accountType: {_eq: "USER"}}, {updatesCountOnUserForTesting: {_gt: 0}}]}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-or", + query: `{ User(where: {_or: [{id: {_eq: "user-1"}}, {id: {_eq: "user-2"}}]}, order_by: {id: asc}) { id } }`, + bench: true, + }, + { + name: "where-not", + query: `{ User(where: {_not: {accountType: {_eq: "ADMIN"}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-nested-and-or-not", + query: `{ User(where: {_or: [{_and: [{accountType: {_eq: "ADMIN"}}, {_not: {updatesCountOnUserForTesting: {_lt: 0}}}]}, {id: {_like: "%quoted%"}}]}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-empty-bool-exp", + query: `{ SimpleEntity(where: {}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-and-empty-list", + query: `{ SimpleEntity(where: {_and: []}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-or-empty-list", + query: `{ SimpleEntity(where: {_or: []}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-object-relationship", + query: `{ Gravatar(where: {owner: {accountType: {_eq: "ADMIN"}}}, order_by: {id: asc}) { id owner { id } } }`, + }, + { + name: "where-array-relationship", + query: `{ User(where: {tokens: {tokenId: {_gte: "9"}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-relationship-nested-two-levels", + query: `{ NftCollection(where: {tokens: {owner: {accountType: {_eq: "ADMIN"}}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-relationship-is-null-object", + query: `{ User(where: {gravatar: {id: {_is_null: false}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-multiple-ops-same-column", + query: `{ Token(where: {tokenId: {_gte: 1, _lte: 10, _neq: 8}}, order_by: {id: asc}) { id tokenId } }`, + }, + { + name: "where-unicode-value", + query: `{ EntityWithAllNonArrayTypes(where: {string: {_eq: "héllo wörld 中文测试 🚀🎉"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-empty-string-eq", + query: `{ EntityWithAllNonArrayTypes(where: {string: {_eq: ""}}, order_by: {id: asc}) { id } }`, + }, + { + name: "where-variables-bool-exp", + query: `query ($w: User_bool_exp!) { User(where: $w, order_by: {id: asc}) { id } }`, + variables: { w: { accountType: { _eq: "ADMIN" } } }, + }, + { + name: "where-variables-nested-exp", + query: `query ($w: User_bool_exp) { User(where: $w, order_by: {id: asc}) { id } }`, + variables: { + w: { _or: [{ id: { _eq: "user-1" } }, { tokens: { tokenId: { _eq: 8 } } }] }, + }, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/03-order-pagination.ts b/packages/e2e-tests/src/differential/corpus/03-order-pagination.ts new file mode 100644 index 0000000000..051b63d838 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/03-order-pagination.ts @@ -0,0 +1,128 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "order-asc", + query: `{ Token(order_by: {tokenId: asc}) { id tokenId } }`, + bench: true, + }, + { + name: "order-desc", + query: `{ Token(order_by: {tokenId: desc}) { id tokenId } }`, + }, + { + name: "order-nulls-first", + query: `{ User(order_by: {gravatar_id: asc_nulls_first, id: asc}) { id gravatar_id } }`, + }, + { + name: "order-nulls-last", + query: `{ User(order_by: {gravatar_id: asc_nulls_last, id: asc}) { id gravatar_id } }`, + }, + { + name: "order-desc-nulls-first", + query: `{ User(order_by: {gravatar_id: desc_nulls_first, id: asc}) { id gravatar_id } }`, + }, + { + name: "order-desc-nulls-last", + query: `{ User(order_by: {gravatar_id: desc_nulls_last, id: asc}) { id gravatar_id } }`, + }, + { + name: "order-default-nulls-asc", + query: `{ User(order_by: {gravatar_id: asc, id: asc}) { id gravatar_id } }`, + }, + { + name: "order-default-nulls-desc", + query: `{ User(order_by: {gravatar_id: desc, id: asc}) { id gravatar_id } }`, + }, + { + name: "order-multi-key-list", + query: `{ SimulateTestEvent(order_by: [{blockNumber: desc}, {logIndex: asc}]) { id blockNumber logIndex } }`, + }, + { + name: "order-multi-key-single-object", + query: `{ SimulateTestEvent(order_by: {blockNumber: desc, logIndex: desc}) { id blockNumber logIndex } }`, + }, + { + name: "order-by-enum-column", + query: `{ Gravatar(order_by: [{size: asc}, {id: asc}]) { id size } }`, + }, + { + name: "order-by-numeric", + query: `{ Token(order_by: [{tokenId: desc}, {id: asc}]) { id tokenId } }`, + }, + { + name: "order-by-timestamp", + query: `{ EntityWithTimestamp(order_by: [{timestamp: asc}, {id: asc}]) { id timestamp } }`, + }, + { + name: "order-by-bool", + query: `{ EntityWithAllNonArrayTypes(order_by: [{bool: asc}, {id: asc}]) { id bool } }`, + }, + { + name: "order-by-float-with-special", + query: `{ EntityWithAllNonArrayTypes(order_by: [{float_: asc}, {id: asc}]) { id float_ } }`, + }, + { + name: "order-by-object-relationship-column", + query: `{ Gravatar(order_by: [{owner: {updatesCountOnUserForTesting: desc}}, {id: asc}]) { id owner { updatesCountOnUserForTesting } } }`, + }, + { + name: "order-by-relationship-nested", + query: `{ Token(order_by: [{collection: {name: asc}}, {id: asc}]) { id collection { name } } }`, + }, + { + name: "limit-zero", + query: `{ User(order_by: {id: asc}, limit: 0) { id } }`, + }, + { + name: "limit-basic", + query: `{ SimpleEntity(order_by: {id: asc}, limit: 3) { id } }`, + bench: true, + }, + { + name: "limit-larger-than-rows", + query: `{ SimpleEntity(order_by: {id: asc}, limit: 5000) { id } }`, + }, + { + name: "offset-basic", + query: `{ SimpleEntity(order_by: {id: asc}, offset: 3) { id } }`, + }, + { + name: "offset-beyond-rows", + query: `{ SimpleEntity(order_by: {id: asc}, offset: 500) { id } }`, + }, + { + name: "limit-offset-combo", + query: `{ SimpleEntity(order_by: {id: asc}, limit: 2, offset: 2) { id } }`, + }, + { + name: "offset-without-order", + query: `{ SimpleEntity(offset: 8) { id } }`, + compare: "rootSet", + }, + { + name: "distinct-on-basic", + query: `{ Token(distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}]) { id owner_id tokenId } }`, + }, + { + name: "distinct-on-list", + query: `{ SimulateTestEvent(distinct_on: [blockNumber], order_by: [{blockNumber: asc}, {logIndex: desc}]) { id blockNumber logIndex } }`, + }, + { + name: "distinct-on-multiple-columns", + query: `{ SimulateTestEvent(distinct_on: [blockNumber, timestamp], order_by: [{blockNumber: asc}, {timestamp: asc}, {logIndex: asc}]) { id blockNumber timestamp } }`, + }, + { + name: "distinct-on-with-limit", + query: `{ Token(distinct_on: collection_id, order_by: [{collection_id: asc}, {tokenId: desc}], limit: 2) { id collection_id } }`, + }, + { + name: "distinct-on-enum-column", + query: `{ Gravatar(distinct_on: size, order_by: [{size: asc}, {id: asc}]) { id size } }`, + }, + { + name: "variables-limit-offset-order", + query: `query ($l: Int, $o: Int, $ord: [SimpleEntity_order_by!]) { SimpleEntity(limit: $l, offset: $o, order_by: $ord) { id } }`, + variables: { l: 3, o: 1, ord: [{ id: "desc" }] }, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/04-relationships.ts b/packages/e2e-tests/src/differential/corpus/04-relationships.ts new file mode 100644 index 0000000000..f1bb680c36 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/04-relationships.ts @@ -0,0 +1,80 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "rel-object-basic", + query: `{ Gravatar(order_by: {id: asc}) { id owner { id address accountType } } }`, + bench: true, + }, + { + name: "rel-object-dangling", + query: `{ Gravatar(where: {id: {_eq: "grav-3"}}) { id owner { id } } }`, + }, + { + name: "rel-object-nullable-fk", + query: `{ User(order_by: {id: asc}) { id gravatar { id displayName size } } }`, + }, + { + name: "rel-array-basic", + query: `{ User(order_by: {id: asc}) { id tokens(order_by: {id: asc}) { id tokenId } } }`, + bench: true, + }, + { + name: "rel-array-empty", + query: `{ User(where: {id: {_eq: "user-dangling"}}) { id tokens(order_by: {id: asc}) { id } } }`, + }, + { + name: "rel-array-nested-args", + query: `{ User(order_by: {id: asc}) { id tokens(where: {tokenId: {_gte: 2}}, order_by: {tokenId: desc}, limit: 2) { id tokenId } } }`, + }, + { + name: "rel-array-nested-offset", + query: `{ NftCollection(order_by: {id: asc}) { id tokens(order_by: {tokenId: asc}, limit: 2, offset: 1) { id tokenId } } }`, + }, + { + name: "rel-array-distinct-on", + query: `{ NftCollection(order_by: {id: asc}) { id tokens(distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}]) { id owner_id } } }`, + }, + { + name: "rel-deep-nesting", + query: `{ NftCollection(order_by: {id: asc}, limit: 2) { id tokens(order_by: {id: asc}, limit: 3) { id owner { id gravatar { id displayName } } } } }`, + }, + { + name: "rel-circular-nesting", + query: `{ User(where: {id: {_eq: "user-1"}}) { id tokens(order_by: {id: asc}) { id owner { id tokens(order_by: {id: asc}, limit: 1) { id } } } } }`, + }, + { + name: "rel-abcd-chain", + query: `{ B(order_by: {id: asc}) { id c { id a { id b { id } } } a(order_by: {id: asc}) { id optionalStringToTestLinkedEntities } } }`, + }, + { + name: "rel-derived-from-id-typed-key", + query: `{ C(order_by: {id: asc}) { id d(order_by: {id: asc}) { id c } } }`, + }, + { + name: "rel-aliases-multiple-same-relationship", + query: `{ User(where: {id: {_eq: "user-1"}}) { id low: tokens(where: {tokenId: {_lt: 1}}, order_by: {id: asc}) { id } high: tokens(where: {tokenId: {_gte: 1}}, order_by: {id: asc}) { id } } }`, + }, + { + name: "rel-fragment-on-relationship", + query: `fragment TokenBits on Token { id tokenId collection { symbol } } { User(order_by: {id: asc}, limit: 3) { id tokens(order_by: {id: asc}) { ...TokenBits } } }`, + }, + { + name: "rel-typename-in-nested", + query: `{ Gravatar(order_by: {id: asc}, limit: 2) { __typename owner { __typename id } } }`, + }, + { + name: "rel-where-on-parent-and-child", + query: `{ User(where: {tokens: {collection: {symbol: {_eq: "ALPHA"}}}}, order_by: {id: asc}) { id tokens(where: {collection: {symbol: {_eq: "ALPHA"}}}, order_by: {id: asc}) { id collection { symbol } } } }`, + }, + { + name: "rel-order-parent-by-child-aggregate-count", + query: `{ User(order_by: [{tokens_aggregate: {count: desc}}, {id: asc}]) { id } }`, + role: "admin", + }, + { + name: "rel-order-parent-by-child-aggregate-max", + query: `{ NftCollection(order_by: [{tokens_aggregate: {max: {tokenId: desc_nulls_last}}}, {id: asc}]) { id } }`, + role: "admin", + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/05-scalars.ts b/packages/e2e-tests/src/differential/corpus/05-scalars.ts new file mode 100644 index 0000000000..e6004a9df0 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/05-scalars.ts @@ -0,0 +1,86 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "scalars-all-non-array-full", + query: `{ EntityWithAllNonArrayTypes(order_by: {id: asc}) { id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp } }`, + bench: true, + }, + { + name: "scalars-all-types-full", + query: `{ EntityWithAllTypes(order_by: {id: asc}) { id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField } }`, + bench: true, + }, + { + name: "scalars-numeric-precision-monsters", + query: `{ PostgresNumericPrecisionEntityTester(order_by: {id: asc}) { id exampleBigInt exampleBigIntRequired exampleBigIntArray exampleBigIntArrayRequired exampleBigDecimal exampleBigDecimalRequired exampleBigDecimalArray exampleBigDecimalArrayRequired exampleBigDecimalOtherOrder } }`, + }, + { + name: "scalars-float-special-values", + query: `{ EntityWithAllNonArrayTypes(where: {id: {_in: ["scalar-special-float", "scalar-neg-inf", "scalar-extremes"]}}, order_by: {id: asc}) { id float_ optFloat } }`, + }, + { + name: "scalars-bigdecimal-trailing-zeros", + query: `{ EntityWithBigDecimal(order_by: {id: asc}) { id bigDecimal } }`, + }, + { + name: "scalars-timestamp-precision", + query: `{ EntityWithTimestamp(order_by: {id: asc}) { id timestamp } }`, + }, + { + name: "scalars-jsonb-variants", + query: `{ EntityWithAllTypes(where: {id: {_like: "all-json%"}}, order_by: {id: asc}) { id json } }`, + }, + { + name: "scalars-jsonb-path-arg", + query: `{ EntityWithAllTypes(where: {id: {_eq: "all-1"}}) { id json(path: "$.nested.a") } }`, + }, + { + name: "scalars-jsonb-path-index", + query: `{ EntityWithAllTypes(where: {id: {_eq: "all-array-edge"}}) { id json(path: "$[4].k") } }`, + }, + { + name: "scalars-jsonb-path-missing", + query: `{ EntityWithAllTypes(where: {id: {_eq: "all-1"}}) { id json(path: "$.does.not.exist") } }`, + }, + { + name: "scalars-jsonb-contains", + query: `{ EntityWithAllTypes(where: {json: {_contains: {kind: "object"}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "scalars-jsonb-contained-in", + query: `{ EntityWithAllTypes(where: {json: {_contained_in: {kind: "object", n: 1, nested: {a: [1, 2]}, extra: true}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "scalars-jsonb-has-key", + query: `{ EntityWithAllTypes(where: {json: {_has_key: "nested"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "scalars-jsonb-has-keys-any", + query: `{ EntityWithAllTypes(where: {json: {_has_keys_any: ["kind", "héllo"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "scalars-jsonb-has-keys-all", + query: `{ EntityWithAllTypes(where: {json: {_has_keys_all: ["kind", "n"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "scalars-string-arrays-escaping", + query: `{ EntityWithAllTypes(where: {id: {_eq: "all-array-edge"}}) { id arrayOfStrings } }`, + }, + { + name: "scalars-empty-arrays", + query: `{ EntityWithAllTypes(where: {id: {_eq: "all-empty-arrays"}}) { id arrayOfStrings arrayOfInts arrayOfFloats arrayOfBigInts arrayOfBigDecimals } }`, + }, + { + name: "scalars-numeric-array-precision", + query: `{ PostgresNumericPrecisionEntityTester(where: {id: {_eq: "prec-1"}}) { id exampleBigIntArray exampleBigDecimalArray } }`, + }, + { + name: "scalars-unicode-strings", + query: `{ EntityWithAllNonArrayTypes(where: {id: {_in: ["scalar-unicode", "scalar-quotes"]}}, order_by: {id: asc}) { id string optString } }`, + }, + { + name: "scalars-where-on-array-column-eq", + query: `{ EntityWithAllTypes(where: {arrayOfStrings: {_eq: ["one", "two", "three"]}}, order_by: {id: asc}) { id } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/06-aggregates.ts b/packages/e2e-tests/src/differential/corpus/06-aggregates.ts new file mode 100644 index 0000000000..936ebb59c7 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/06-aggregates.ts @@ -0,0 +1,121 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "agg-count-basic", + role: "admin", + query: `{ User_aggregate { aggregate { count } } }`, + bench: true, + }, + { + name: "agg-count-with-where", + role: "admin", + query: `{ User_aggregate(where: {accountType: {_eq: "ADMIN"}}) { aggregate { count } } }`, + }, + { + name: "agg-count-column", + role: "admin", + query: `{ User_aggregate { aggregate { count(columns: gravatar_id) } } }`, + }, + { + name: "agg-count-distinct", + role: "admin", + query: `{ Token_aggregate { aggregate { count(columns: owner_id, distinct: true) } } }`, + }, + { + name: "agg-count-distinct-false", + role: "admin", + query: `{ Token_aggregate { aggregate { count(columns: owner_id, distinct: false) } } }`, + }, + { + name: "agg-min-max-int", + role: "admin", + query: `{ User_aggregate { aggregate { min { updatesCountOnUserForTesting } max { updatesCountOnUserForTesting } } } }`, + }, + { + name: "agg-min-max-string", + role: "admin", + query: `{ SimpleEntity_aggregate { aggregate { min { id value } max { id value } } } }`, + }, + { + name: "agg-min-max-numeric", + role: "admin", + query: `{ Token_aggregate { aggregate { min { tokenId } max { tokenId } } } }`, + }, + { + name: "agg-min-max-timestamp", + role: "admin", + query: `{ EntityWithTimestamp_aggregate { aggregate { min { timestamp } max { timestamp } } } }`, + }, + { + name: "agg-sum-avg-numeric", + role: "admin", + query: `{ Token_aggregate { aggregate { sum { tokenId } avg { tokenId } } } }`, + }, + { + name: "agg-sum-avg-int-float", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate(where: {id: {_in: ["scalar-1", "scalar-nulls", "scalar-empty"]}}) { aggregate { sum { int_ float_ bigInt bigDecimal } avg { int_ float_ } } } }`, + }, + { + name: "agg-stddev-variance", + role: "admin", + query: `{ SimulateTestEvent_aggregate { aggregate { stddev { blockNumber } stddev_pop { blockNumber } stddev_samp { blockNumber } variance { blockNumber } var_pop { blockNumber } var_samp { blockNumber } } } }`, + }, + { + name: "agg-empty-set", + role: "admin", + query: `{ User_aggregate(where: {id: {_eq: "missing"}}) { aggregate { count sum { updatesCountOnUserForTesting } avg { updatesCountOnUserForTesting } min { id } max { id } } } }`, + }, + { + name: "agg-nodes", + role: "admin", + query: `{ SimpleEntity_aggregate(order_by: {id: asc}, limit: 3) { aggregate { count } nodes { id value } } }`, + }, + { + name: "agg-nodes-only", + role: "admin", + query: `{ SimpleEntity_aggregate(order_by: {id: desc}, limit: 2) { nodes { id } } }`, + }, + { + name: "agg-with-limit-offset", + role: "admin", + query: `{ SimpleEntity_aggregate(order_by: {id: asc}, limit: 4, offset: 2) { aggregate { count } nodes { id } } }`, + }, + { + name: "agg-with-distinct-on", + role: "admin", + query: `{ Token_aggregate(distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}]) { aggregate { count } nodes { id owner_id } } }`, + }, + { + name: "agg-nested-array-relationship", + role: "admin", + query: `{ User(order_by: {id: asc}) { id tokens_aggregate { aggregate { count sum { tokenId } } } } }`, + bench: true, + }, + { + name: "agg-nested-with-args", + role: "admin", + query: `{ NftCollection(order_by: {id: asc}) { id tokens_aggregate(where: {tokenId: {_gte: 1}}, order_by: {tokenId: asc}) { aggregate { count max { tokenId } } nodes { id } } } }`, + }, + { + name: "agg-aliases", + role: "admin", + query: `{ total: User_aggregate { aggregate { c: count } } admins: User_aggregate(where: {accountType: {_eq: "ADMIN"}}) { aggregate { count } } }`, + }, + { + name: "agg-typename", + role: "admin", + query: `{ User_aggregate { __typename aggregate { __typename count } } }`, + }, + { + name: "agg-public-role-denied", + role: "public", + query: `{ User_aggregate { aggregate { count } } }`, + }, + { + name: "agg-nested-public-role-denied", + role: "public", + query: `{ User(order_by: {id: asc}, limit: 1) { id tokens_aggregate { aggregate { count } } } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/07-internal-tables.ts b/packages/e2e-tests/src/differential/corpus/07-internal-tables.ts new file mode 100644 index 0000000000..b7363b58b9 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/07-internal-tables.ts @@ -0,0 +1,59 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "internal-meta-view", + query: `{ _meta { chainId startBlock endBlock progressBlock bufferBlock firstEventBlock eventsProcessed sourceBlock readyAt isReady } }`, + bench: true, + }, + { + name: "internal-meta-float4-precision", + query: `{ _meta(where: {chainId: {_eq: 1}}) { chainId eventsProcessed } }`, + }, + { + name: "internal-meta-where-ready", + query: `{ _meta(where: {isReady: {_eq: true}}) { chainId readyAt } }`, + }, + { + name: "internal-chain-metadata-view", + query: `{ chain_metadata(order_by: {chain_id: asc}) { block_height chain_id end_block first_event_block_number is_hyper_sync latest_fetched_block_number latest_processed_block num_batches_fetched num_events_processed start_block timestamp_caught_up_to_head_or_endblock } }`, + }, + { + name: "internal-raw-events-full", + query: `{ raw_events(order_by: {serial: asc}) { chain_id event_id event_name contract_name block_number log_index src_address block_hash block_timestamp block_fields transaction_fields params serial } }`, + bench: true, + }, + { + name: "internal-raw-events-by-pk", + query: `{ raw_events_by_pk(serial: 1) { serial event_name params } }`, + }, + { + name: "internal-raw-events-by-pk-miss", + query: `{ raw_events_by_pk(serial: 999999) { serial } }`, + }, + { + name: "internal-raw-events-bigint-filter", + query: `{ raw_events(where: {event_id: {_gt: "4611686018427387904"}}, order_by: {serial: asc}) { serial event_id } }`, + }, + { + name: "internal-raw-events-jsonb-filter", + query: `{ raw_events(where: {params: {_has_key: "from"}}, order_by: {serial: asc}) { serial params } }`, + }, + { + name: "internal-raw-events-jsonb-path", + query: `{ raw_events(where: {event_name: {_eq: "NewGravatar"}}) { serial params(path: "$.nested.deep[0]") } }`, + }, + { + name: "internal-no-relationships-on-internal-tables", + query: `{ raw_events(limit: 1, order_by: {serial: asc}) { serial } _meta(limit: 1) { chainId } }`, + }, + { + name: "internal-meta-aggregate-admin", + role: "admin", + query: `{ _meta_aggregate { aggregate { count max { eventsProcessed } } } }`, + }, + { + name: "internal-chain-metadata-no-by-pk", + query: `{ chain_metadata(where: {chain_id: {_eq: 1337}}) { chain_id end_block timestamp_caught_up_to_head_or_endblock } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/08-errors.ts b/packages/e2e-tests/src/differential/corpus/08-errors.ts new file mode 100644 index 0000000000..24d54a4858 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/08-errors.ts @@ -0,0 +1,179 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "error-unknown-root-field", + query: `{ NotATable { id } }`, + }, + { + name: "error-unknown-column", + query: `{ User { id notAColumn } }`, + }, + { + name: "error-unknown-argument", + query: `{ User(bogus: 1) { id } }`, + }, + { + name: "error-syntax", + query: `{ User { id `, + }, + { + name: "error-empty-query", + query: ``, + }, + { + name: "error-no-selection-set", + query: `{ User }`, + }, + { + name: "error-scalar-with-selection", + query: `{ User(limit: 1) { id { nested } } }`, + }, + { + name: "error-by-pk-missing-arg", + query: `{ User_by_pk { id } }`, + }, + { + name: "error-by-pk-wrong-arg-type", + query: `{ User_by_pk(id: 5) { id } }`, + }, + { + name: "error-invalid-enum-value", + query: `{ User(where: {accountType: {_eq: "NOPE"}}) { id } }`, + }, + { + name: "error-enum-as-string-order-by", + query: `{ User(order_by: {id: "asc"}) { id } }`, + }, + { + name: "error-limit-string", + query: `{ User(limit: "5") { id } }`, + }, + { + name: "error-negative-limit", + query: `{ User(limit: -1) { id } }`, + }, + { + name: "error-negative-offset", + query: `{ SimpleEntity(order_by: {id: asc}, offset: -5) { id } }`, + }, + { + name: "error-unknown-op-in-bool-exp", + query: `{ User(where: {id: {_bogus: "x"}}) { id } }`, + }, + { + name: "error-eq-null-literal", + query: `{ User(where: {gravatar_id: {_eq: null}}) { id } }`, + }, + { + name: "error-where-wrong-type", + query: `{ User(where: {updatesCountOnUserForTesting: {_eq: "not-an-int"}}) { id } }`, + }, + { + name: "error-int-overflow-filter", + query: `{ User(where: {updatesCountOnUserForTesting: {_eq: 99999999999999}}) { id } }`, + }, + { + name: "error-float-for-int-filter", + query: `{ User(where: {updatesCountOnUserForTesting: {_eq: 1.5}}) { id } }`, + }, + { + name: "error-missing-required-variable", + query: `query ($id: String!) { User_by_pk(id: $id) { id } }`, + }, + { + name: "error-null-for-required-variable", + query: `query ($id: String!) { User_by_pk(id: $id) { id } }`, + variables: { id: null }, + }, + { + name: "error-variable-wrong-type", + query: `query ($id: String!) { User_by_pk(id: $id) { id } }`, + variables: { id: 42 }, + }, + { + name: "error-unused-variable", + query: `query ($unused: Int) { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }`, + variables: { unused: 1 }, + }, + { + name: "error-undeclared-variable-used", + query: `{ User(limit: $lim) { id } }`, + variables: { lim: 1 }, + }, + { + name: "error-unknown-variable-type", + query: `query ($w: Bogus_bool_exp) { User { id } }`, + }, + { + name: "error-multiple-anonymous-operations", + query: `{ User(limit: 1) { id } } { Gravatar(limit: 1) { id } }`, + }, + { + name: "error-operation-name-not-found", + query: `query A { User(limit: 1) { id } }`, + operationName: "B", + }, + { + name: "error-multiple-ops-no-operation-name", + query: `query A { User(limit: 1) { id } } query B { Gravatar(limit: 1) { id } }`, + }, + { + name: "error-duplicate-operation-names", + query: `query A { User(limit: 1) { id } } query A { Gravatar(limit: 1) { id } }`, + operationName: "A", + }, + { + name: "error-fragment-unknown-type", + query: `fragment F on Bogus { id } { User(limit: 1) { ...F } }`, + }, + { + name: "error-fragment-undefined", + query: `{ User(limit: 1) { ...NoSuchFragment } }`, + }, + { + name: "error-fragment-unused", + query: `fragment Unused on User { id } { User(limit: 1) { id } }`, + }, + { + name: "error-fragment-cycle", + query: `fragment A1 on User { ...B1 } fragment B1 on User { ...A1 } { User(limit: 1) { ...A1 } }`, + }, + { + name: "error-mutation-public", + query: `mutation { insert_User(objects: [{id: "x", address: "0x", updatesCountOnUserForTesting: 0, accountType: "USER"}]) { affected_rows } }`, + }, + { + name: "error-subscription-over-http", + query: `subscription { User(limit: 1) { id } }`, + }, + { + name: "error-aggregate-public-not-exposed", + query: `{ Token_aggregate { aggregate { count } } }`, + }, + { + name: "error-distinct-on-without-matching-order", + query: `{ Token(distinct_on: owner_id, order_by: {tokenId: asc}) { id } }`, + }, + { + name: "error-jsonb-path-invalid", + query: `{ EntityWithAllTypes(where: {id: {_eq: "all-1"}}) { json(path: "totally broken [") } }`, + }, + { + name: "error-like-on-int-column", + query: `{ User(where: {updatesCountOnUserForTesting: {_like: "%1%"}}) { id } }`, + }, + { + name: "error-directive-unknown", + query: `{ User(limit: 1) { id @bogus } }`, + }, + { + name: "error-skip-missing-if", + query: `{ User(limit: 1) { id @skip } }`, + }, + { + name: "error-admin-secret-wrong", + role: "admin-wrong", + query: `{ User(limit: 1) { id } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/09-introspection.ts b/packages/e2e-tests/src/differential/corpus/09-introspection.ts new file mode 100644 index 0000000000..401ddd8e48 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/09-introspection.ts @@ -0,0 +1,124 @@ +import { defineCases } from "../corpus.js"; + +const FULL_INTROSPECTION = ` +query IntrospectionQuery { + __schema { + queryType { name } + mutationType { name } + subscriptionType { name } + types { ...FullType } + directives { name description locations args { ...InputValue } } + } +} +fragment FullType on __Type { + kind name description + fields(includeDeprecated: true) { + name description + args { ...InputValue } + type { ...TypeRef } + isDeprecated deprecationReason + } + inputFields { ...InputValue } + interfaces { ...TypeRef } + enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason } + possibleTypes { ...TypeRef } +} +fragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue } +fragment TypeRef on __Type { + kind name + ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } +}`; + +export default defineCases([ + { + name: "introspection-full-public", + query: FULL_INTROSPECTION, + }, + // The admin schema is compared per-read-feature below instead of via full + // introspection: envio serve is read-only, so Hasura's admin mutation + // surface (mutation_root + insert_/update_/delete_ types) is out of scope. + { + name: "introspection-admin-query-root", + role: "admin", + query: `{ __type(name: "query_root") { fields { name description args { name description type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } defaultValue } type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } }`, + }, + { + name: "introspection-admin-subscription-root", + role: "admin", + query: `{ __type(name: "subscription_root") { fields { name description args { name type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } type { kind name } } } }`, + }, + { + name: "introspection-full-public-limited", + phases: ["limited"], + query: FULL_INTROSPECTION, + }, + { + name: "introspection-typename-meta", + query: `{ __schema { queryType { name } } }`, + }, + { + name: "introspection-type-entity", + query: `{ __type(name: "User") { kind name description fields { name type { kind name ofType { kind name ofType { kind name } } } } } }`, + }, + { + name: "introspection-descriptions", + query: `{ __type(name: "User") { description fields { name description } } }`, + }, + { + name: "introspection-descriptions-stream-cursor-value-input", + query: `{ __type(name: "User_stream_cursor_value_input") { inputFields { name description } } }`, + }, + { + name: "introspection-descriptions-bool-exp-and-order-by", + query: `{ bool_exp: __type(name: "User_bool_exp") { inputFields { name description } } order_by: __type(name: "User_order_by") { inputFields { name description } } }`, + }, + { + name: "introspection-type-bool-exp", + query: `{ __type(name: "User_bool_exp") { kind name inputFields { name type { kind name ofType { kind name ofType { kind name } } } } } }`, + }, + { + name: "introspection-type-comparison-exp", + query: `{ __type(name: "numeric_comparison_exp") { kind name inputFields { name type { kind name ofType { kind name } } } } }`, + }, + { + name: "introspection-type-order-by-enum", + query: `{ __type(name: "order_by") { kind name enumValues { name description } } }`, + }, + { + name: "introspection-type-select-column", + query: `{ __type(name: "Token_select_column") { kind name enumValues { name description } } }`, + }, + { + name: "introspection-type-pg-enum-scalar", + query: `{ __type(name: "accounttype") { kind name description } }`, + }, + { + name: "introspection-type-missing", + query: `{ __type(name: "DoesNotExist") { kind name } }`, + }, + { + name: "introspection-aggregate-types-admin", + role: "admin", + query: `{ agg: __type(name: "Token_aggregate_fields") { fields { name args { name defaultValue type { kind name ofType { kind name } } } type { kind name ofType { kind name } } } } sum: __type(name: "Token_sum_fields") { fields { name type { name } } } }`, + }, + { + name: "introspection-aggregate-types-hidden-public", + query: `{ __type(name: "Token_aggregate_fields") { name } }`, + }, + { + name: "introspection-stream-cursor-types", + query: `{ cursor: __type(name: "User_stream_cursor_input") { inputFields { name type { kind name ofType { kind name } } } } value: __type(name: "User_stream_cursor_value_input") { inputFields { name type { kind name } } } ordering: __type(name: "cursor_ordering") { enumValues { name description } } }`, + }, + { + name: "introspection-typename-on-typed-queries", + query: `{ __type(name: "User") { __typename } __schema { __typename } }`, + }, + { + name: "introspection-mixed-with-data", + query: `{ __schema { queryType { name } } User(order_by: {id: asc}, limit: 1) { id __typename } }`, + }, + { + name: "introspection-deprecated-flag", + query: `{ __type(name: "query_root") { fields(includeDeprecated: true) { name isDeprecated } } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/10-limits.ts b/packages/e2e-tests/src/differential/corpus/10-limits.ts new file mode 100644 index 0000000000..976280d122 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/10-limits.ts @@ -0,0 +1,70 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "limits-response-limit-caps-rows", + phases: ["limited"], + query: `{ SimpleEntity(order_by: {id: asc}) { id } }`, + }, + { + name: "limits-response-limit-explicit-higher", + phases: ["limited"], + query: `{ SimpleEntity(order_by: {id: asc}, limit: 9) { id } }`, + }, + { + name: "limits-response-limit-explicit-lower", + phases: ["limited"], + query: `{ SimpleEntity(order_by: {id: asc}, limit: 2) { id } }`, + }, + { + name: "limits-response-limit-with-offset", + phases: ["limited"], + query: `{ SimpleEntity(order_by: {id: asc}, offset: 7) { id } }`, + }, + { + name: "limits-admin-not-capped", + phases: ["limited"], + role: "admin", + query: `{ SimpleEntity(order_by: {id: asc}) { id } }`, + }, + { + name: "limits-nested-relationship-capped", + phases: ["limited"], + query: `{ User(where: {id: {_eq: "user-1"}}) { id tokens(order_by: {id: asc}) { id } } }`, + }, + { + name: "limits-by-pk-unaffected", + phases: ["limited"], + query: `{ SimpleEntity_by_pk(id: "simple-9") { id } }`, + }, + { + name: "limits-public-aggregate-enabled", + phases: ["limited"], + query: `{ User_aggregate { aggregate { count } } }`, + }, + { + name: "limits-public-aggregate-count-exceeds-limit", + phases: ["limited"], + query: `{ SimpleEntity_aggregate { aggregate { count } nodes { id } } }`, + }, + { + name: "limits-public-aggregate-not-enabled-table", + phases: ["limited"], + query: `{ Gravatar_aggregate { aggregate { count } } }`, + }, + { + name: "limits-public-nested-aggregate-enabled", + phases: ["limited"], + query: `{ User(order_by: {id: asc}, limit: 2) { id tokens_aggregate { aggregate { count } } } }`, + }, + { + name: "limits-meta-aggregate-enabled", + phases: ["limited"], + query: `{ _meta_aggregate { aggregate { count } } }`, + }, + { + name: "limits-raw-events-capped", + phases: ["limited"], + query: `{ raw_events(order_by: {serial: asc}) { serial } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/11-where-matrix.ts b/packages/e2e-tests/src/differential/corpus/11-where-matrix.ts new file mode 100644 index 0000000000..928cd57170 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/11-where-matrix.ts @@ -0,0 +1,313 @@ +import { defineCases } from "../corpus.js"; + +// Exhaustive where-operator matrix per scalar type. Complementary operators +// (op and its negation) are paired as aliased roots in one case so the +// snapshot pins that the negative operator is the exact complement on +// NOT NULL columns. +export default defineCases([ + // ── text (User.address) ────────────────────────────────────────────── + { + name: "wm-text-eq-neq", + query: `{ eq: User(where: {address: {_eq: "0xaaaa000000000000000000000000000000000003"}}, order_by: {id: asc}) { id address } neq: User(where: {address: {_neq: "0xaaaa000000000000000000000000000000000003"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-text-gt-gte", + query: `{ gt: User(where: {address: {_gt: "0xaaaa000000000000000000000000000000000004"}}, order_by: {id: asc}) { id } gte: User(where: {address: {_gte: "0xaaaa000000000000000000000000000000000004"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-text-lt-lte", + query: `{ lt: User(where: {address: {_lt: "0xaaaa000000000000000000000000000000000002"}}, order_by: {id: asc}) { id } lte: User(where: {address: {_lte: "0xaaaa000000000000000000000000000000000002"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-text-in-nin", + query: `{ in: User(where: {address: {_in: ["0xaaaa000000000000000000000000000000000002", "0xaaaa000000000000000000000000000000000005", "0xmissing"]}}, order_by: {id: asc}) { id } nin: User(where: {address: {_nin: ["0xaaaa000000000000000000000000000000000002", "0xaaaa000000000000000000000000000000000005", "0xmissing"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-text-is-null", + query: `{ isNull: User(where: {address: {_is_null: true}}, order_by: {id: asc}) { id } notNull: User(where: {address: {_is_null: false}}, order_by: {id: asc}) { id } }`, + }, + { + // _nin: [] excludes nothing — every row matches, same as no filter. + name: "wm-text-nin-empty", + query: `{ SimpleEntity(where: {id: {_nin: []}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-text-like-nlike", + query: `{ like: User(where: {address: {_like: "%00000_"}}, order_by: {id: asc}) { id } nlike: User(where: {address: {_nlike: "%00000_"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-text-ilike-nilike", + query: `{ ilike: User(where: {address: {_ilike: "0XAAAA%3"}}, order_by: {id: asc}) { id } nilike: User(where: {address: {_nilike: "0XAAAA%3"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-text-similar-nsimilar", + query: `{ similar: User(where: {address: {_similar: "0xaaaa%(1|2)"}}, order_by: {id: asc}) { id } nsimilar: User(where: {address: {_nsimilar: "0xaaaa%(1|2)"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-text-regex-nregex", + query: `{ regex: User(where: {address: {_regex: "000[12]$"}}, order_by: {id: asc}) { id } nregex: User(where: {address: {_nregex: "000[12]$"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-text-iregex-niregex", + query: `{ iregex: User(where: {address: {_iregex: "^0XAAAA.*[56]$"}}, order_by: {id: asc}) { id } niregex: User(where: {address: {_niregex: "^0XAAAA.*[56]$"}}, order_by: {id: asc}) { id } }`, + }, + + // ── Int (User.updatesCountOnUserForTesting / SimulateTestEvent) ────── + { + name: "wm-int-eq-neq", + query: `{ eq: SimulateTestEvent(where: {blockNumber: {_eq: 100}}, order_by: {id: asc}) { id blockNumber } neq: SimulateTestEvent(where: {blockNumber: {_neq: 100}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-int-gt-gte", + query: `{ gt: SimulateTestEvent(where: {logIndex: {_gt: 1}}, order_by: {id: asc}) { id logIndex } gte: SimulateTestEvent(where: {logIndex: {_gte: 1}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-int-lt-lte", + query: `{ lt: User(where: {updatesCountOnUserForTesting: {_lt: 5}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } lte: User(where: {updatesCountOnUserForTesting: {_lte: 5}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-int-in-nin", + query: `{ in: User(where: {updatesCountOnUserForTesting: {_in: [0, 7, 2147483647]}}, order_by: {id: asc}) { id } nin: User(where: {updatesCountOnUserForTesting: {_nin: [0, 7, 2147483647]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-int-is-null", + query: `{ isNull: EntityWithAllNonArrayTypes(where: {optInt: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optInt: {_is_null: false}}, order_by: {id: asc}) { id optInt } }`, + }, + { + name: "wm-int-eq-int32-max", + query: `{ User(where: {updatesCountOnUserForTesting: {_eq: 2147483647}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } }`, + }, + { + name: "wm-int-eq-int32-min", + query: `{ User(where: {updatesCountOnUserForTesting: {_eq: -2147483648}}, order_by: {id: asc}) { id updatesCountOnUserForTesting } }`, + }, + + // ── numeric (Token.tokenId, EntityWithBigDecimal.bigDecimal) ───────── + { + name: "wm-numeric-eq-neq-trailing-zero", + query: `{ eq: EntityWithBigDecimal(where: {bigDecimal: {_eq: "1.1"}}, order_by: {id: asc}) { id bigDecimal } neq: EntityWithBigDecimal(where: {bigDecimal: {_neq: "1.1"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-numeric-gt-gte", + query: `{ gt: EntityWithBigDecimal(where: {bigDecimal: {_gt: "1.1"}}, order_by: {id: asc}) { id bigDecimal } gte: EntityWithBigDecimal(where: {bigDecimal: {_gte: "1.10"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-numeric-lt-lte", + query: `{ lt: EntityWithBigDecimal(where: {bigDecimal: {_lt: 0}}, order_by: {id: asc}) { id bigDecimal } lte: EntityWithBigDecimal(where: {bigDecimal: {_lte: 0}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-numeric-in-nin", + query: `{ in: Token(where: {tokenId: {_in: ["-5", 7, "1000000000000000000000000000000"]}}, order_by: {id: asc}) { id tokenId } nin: Token(where: {tokenId: {_nin: ["-5", 7, "1000000000000000000000000000000"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-numeric-is-null", + query: `{ isNull: EntityWithAllNonArrayTypes(where: {optBigInt: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optBigInt: {_is_null: false}}, order_by: {id: asc}) { id optBigInt } }`, + }, + { + name: "wm-numeric-eq-tiny-fraction", + query: `{ EntityWithBigDecimal(where: {bigDecimal: {_eq: "0.000000000000000001"}}, order_by: {id: asc}) { id bigDecimal } }`, + }, + { + name: "wm-numeric-eq-76-digits", + query: `{ Token(where: {tokenId: {_eq: "9999999999999999999999999999999999999999999999999999999999999999999999999999"}}, order_by: {id: asc}) { id tokenId } }`, + }, + + // ── float8 (EntityWithAllNonArrayTypes.float_) ─────────────────────── + { + name: "wm-float-eq-neq", + query: `{ eq: EntityWithAllNonArrayTypes(where: {float_: {_eq: "-3.14159"}}, order_by: {id: asc}) { id float_ } neq: EntityWithAllNonArrayTypes(where: {float_: {_neq: "-3.14159"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-float-gt-gte-dbl-max", + query: `{ gt: EntityWithAllNonArrayTypes(where: {float_: {_gt: "1.7976931348623157e308"}}, order_by: {id: asc}) { id float_ } gte: EntityWithAllNonArrayTypes(where: {float_: {_gte: "1.7976931348623157e308"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-float-lt-lte", + query: `{ lt: EntityWithAllNonArrayTypes(where: {float_: {_lt: "-0.5"}}, order_by: {id: asc}) { id float_ } lte: EntityWithAllNonArrayTypes(where: {float_: {_lte: "-0.5"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-float-in-nin", + query: `{ in: EntityWithAllNonArrayTypes(where: {float_: {_in: [1.5, "0.1", -0.5]}}, order_by: {id: asc}) { id float_ } nin: EntityWithAllNonArrayTypes(where: {float_: {_nin: [1.5, "0.1", -0.5]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-float-is-null", + query: `{ isNull: EntityWithAllNonArrayTypes(where: {optFloat: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optFloat: {_is_null: false}}, order_by: {id: asc}) { id optFloat } }`, + }, + { + name: "wm-float-eq-infinity-literal", + query: `{ EntityWithAllNonArrayTypes(where: {float_: {_eq: "Infinity"}}, order_by: {id: asc}) { id float_ } }`, + }, + { + name: "wm-float-eq-zero-matches-neg-zero", + query: `{ EntityWithAllNonArrayTypes(where: {optFloat: {_eq: 0}}, order_by: {id: asc}) { id optFloat } }`, + }, + { + name: "wm-float-eq-nan", + query: `{ EntityWithAllNonArrayTypes(where: {optFloat: {_eq: "NaN"}}, order_by: {id: asc}) { id optFloat } }`, + }, + + // ── boolean (EntityWithAllNonArrayTypes.bool) ──────────────────────── + { + name: "wm-bool-eq-neq", + query: `{ eq: EntityWithAllNonArrayTypes(where: {bool: {_eq: false}}, order_by: {id: asc}) { id bool } neq: EntityWithAllNonArrayTypes(where: {bool: {_neq: false}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-bool-gt-gte", + query: `{ gt: EntityWithAllNonArrayTypes(where: {bool: {_gt: false}}, order_by: {id: asc}) { id } gte: EntityWithAllNonArrayTypes(where: {bool: {_gte: true}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-bool-lt-lte", + query: `{ lt: EntityWithAllNonArrayTypes(where: {bool: {_lt: true}}, order_by: {id: asc}) { id } lte: EntityWithAllNonArrayTypes(where: {bool: {_lte: false}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-bool-in-nin", + query: `{ in: EntityWithAllNonArrayTypes(where: {bool: {_in: [false]}}, order_by: {id: asc}) { id } nin: EntityWithAllNonArrayTypes(where: {bool: {_nin: [false]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-bool-is-null", + query: `{ isNull: EntityWithAllNonArrayTypes(where: {optBool: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optBool: {_is_null: false}}, order_by: {id: asc}) { id optBool } }`, + }, + + // ── timestamptz (EntityWithTimestamp.timestamp) ────────────────────── + { + name: "wm-ts-eq-neq", + query: `{ eq: EntityWithTimestamp(where: {timestamp: {_eq: "2024-01-15T12:34:56.123+00:00"}}, order_by: {id: asc}) { id timestamp } neq: EntityWithTimestamp(where: {timestamp: {_neq: "2024-01-15T12:34:56.123+00:00"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-ts-gt-gte", + query: `{ gt: EntityWithTimestamp(where: {timestamp: {_gt: "2024-01-15T12:34:56.123456+00:00"}}, order_by: {id: asc}) { id } gte: EntityWithTimestamp(where: {timestamp: {_gte: "2024-01-15T12:34:56.123456+00:00"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-ts-lt-lte", + query: `{ lt: EntityWithTimestamp(where: {timestamp: {_lt: "1970-01-01T00:00:00+00:00"}}, order_by: {id: asc}) { id timestamp } lte: EntityWithTimestamp(where: {timestamp: {_lte: "1970-01-01T00:00:00+00:00"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-ts-in-nin", + query: `{ in: EntityWithTimestamp(where: {timestamp: {_in: ["1970-01-01T00:00:00Z", "9999-12-31T23:59:59.999999+00:00"]}}, order_by: {id: asc}) { id } nin: EntityWithTimestamp(where: {timestamp: {_nin: ["1970-01-01T00:00:00Z", "9999-12-31T23:59:59.999999+00:00"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-ts-is-null", + query: `{ isNull: EntityWithAllNonArrayTypes(where: {optTimestamp: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optTimestamp: {_is_null: false}}, order_by: {id: asc}) { id optTimestamp } }`, + }, + { + name: "wm-ts-eq-normalized-offset", + query: `{ EntityWithTimestamp(where: {timestamp: {_eq: "2024-06-15T02:30:00+00:00"}}, order_by: {id: asc}) { id timestamp } }`, + }, + + // ── enum scalars (User.accountType, Gravatar.size) ─────────────────── + { + name: "wm-enum-eq-neq", + query: `{ eq: User(where: {accountType: {_eq: "ADMIN"}}, order_by: {id: asc}) { id accountType } neq: User(where: {accountType: {_neq: "ADMIN"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-enum-gt-gte", + query: `{ gt: User(where: {accountType: {_gt: "ADMIN"}}, order_by: {id: asc}) { id accountType } gte: User(where: {accountType: {_gte: "ADMIN"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-enum-lt-lte-declaration-order", + query: `{ lt: Gravatar(where: {size: {_lt: "MEDIUM"}}, order_by: {id: asc}) { id size } lte: Gravatar(where: {size: {_lte: "MEDIUM"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-enum-in-nin", + query: `{ in: Gravatar(where: {size: {_in: ["SMALL", "LARGE"]}}, order_by: {id: asc}) { id size } nin: Gravatar(where: {size: {_nin: ["SMALL", "LARGE"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-enum-is-null", + query: `{ isNull: EntityWithAllNonArrayTypes(where: {optEnumField: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllNonArrayTypes(where: {optEnumField: {_is_null: false}}, order_by: {id: asc}) { id optEnumField } }`, + }, + + // ── text arrays (EntityWithAllTypes.arrayOfStrings) ────────────────── + { + name: "wm-array-eq-neq", + query: `{ eq: EntityWithAllTypes(where: {arrayOfStrings: {_eq: ["one", "two", "three"]}}, order_by: {id: asc}) { id arrayOfStrings } neq: EntityWithAllTypes(where: {arrayOfStrings: {_neq: ["one", "two", "three"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-array-gt-gte", + query: `{ gt: EntityWithAllTypes(where: {arrayOfStrings: {_gt: ["b"]}}, order_by: {id: asc}) { id arrayOfStrings } gte: EntityWithAllTypes(where: {arrayOfStrings: {_gte: ["b"]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-array-lt-lte", + query: `{ lt: EntityWithAllTypes(where: {arrayOfStrings: {_lt: ["b"]}}, order_by: {id: asc}) { id arrayOfStrings } lte: EntityWithAllTypes(where: {arrayOfStrings: {_lte: ["b"]}}, order_by: {id: asc}) { id } }`, + }, + { + // Hasura v2.43 generates broken SQL for _in/_nin on array columns and + // always answers "database query error"; this pins that error shape. + name: "wm-array-in-database-error", + query: `{ EntityWithAllTypes(where: {arrayOfStrings: {_in: [["a"], ["one", "two", "three"]]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-array-is-null", + query: `{ isNull: EntityWithAllTypes(where: {arrayOfStrings: {_is_null: true}}, order_by: {id: asc}) { id } notNull: EntityWithAllTypes(where: {arrayOfStrings: {_is_null: false}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-array-contains-contained-in", + query: `{ contains: EntityWithAllTypes(where: {arrayOfStrings: {_contains: ["two"]}}, order_by: {id: asc}) { id arrayOfStrings } containedIn: EntityWithAllTypes(where: {arrayOfStrings: {_contained_in: ["a", "b", "one", "two", "three"]}}, order_by: {id: asc}) { id } }`, + }, + + // ── bigint (raw_events.event_id) ───────────────────────────────────── + { + name: "wm-bigint-eq-neq", + query: `{ eq: raw_events(where: {event_id: {_eq: "4611686018427387905"}}, order_by: {serial: asc}) { serial event_id } neq: raw_events(where: {event_id: {_neq: "4611686018427387905"}}, order_by: {serial: asc}) { serial } }`, + }, + { + name: "wm-bigint-gt-gte", + query: `{ gt: raw_events(where: {event_id: {_gt: "4611686018427387905"}}, order_by: {serial: asc}) { serial event_id } gte: raw_events(where: {event_id: {_gte: "4611686018427387905"}}, order_by: {serial: asc}) { serial } }`, + }, + { + name: "wm-bigint-lt-lte-int-literal", + query: `{ lt: raw_events(where: {event_id: {_lt: 2}}, order_by: {serial: asc}) { serial event_id } lte: raw_events(where: {event_id: {_lte: 2}}, order_by: {serial: asc}) { serial } }`, + }, + { + name: "wm-bigint-in-nin-mixed-literals", + query: `{ in: raw_events(where: {event_id: {_in: [1, "4611686018427387906"]}}, order_by: {serial: asc}) { serial event_id } nin: raw_events(where: {event_id: {_nin: [1, "4611686018427387906"]}}, order_by: {serial: asc}) { serial } }`, + }, + { + name: "wm-bigint-is-null", + query: `{ isNull: raw_events(where: {event_id: {_is_null: true}}, order_by: {serial: asc}) { serial } notNull: raw_events(where: {event_id: {_is_null: false}}, order_by: {serial: asc}) { serial } }`, + }, + { + name: "wm-bigint-eq-unquoted-64bit-literal", + query: `{ raw_events(where: {event_id: {_eq: 4611686018427387904}}, order_by: {serial: asc}) { serial event_id } }`, + }, + + // ── operator edge combinations ─────────────────────────────────────── + { + name: "wm-in-duplicate-values", + query: `{ Token(where: {tokenId: {_in: [1, 1, "1", 2]}}, order_by: {id: asc}) { id tokenId } }`, + }, + { + name: "wm-in-single-value", + query: `{ SimpleEntity(where: {value: {_in: ["v7"]}}, order_by: {id: asc}) { id value } }`, + }, + { + name: "wm-is-null-false-with-like", + query: `{ User(where: {gravatar_id: {_is_null: false, _like: "grav-%"}}, order_by: {id: asc}) { id gravatar_id } }`, + }, + { + name: "wm-is-null-true-with-eq", + query: `{ User(where: {gravatar_id: {_is_null: true, _eq: "grav-1"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-jsonb-eq-object-literal", + query: `{ raw_events(where: {params: {_eq: {from: "0x0", to: "0x1", value: "100"}}}, order_by: {serial: asc}) { serial params } }`, + }, + { + name: "wm-jsonb-eq-empty-object", + query: `{ EntityWithAllTypes(where: {json: {_eq: {}}}, order_by: {id: asc}) { id json } }`, + }, + { + name: "wm-jsonb-eq-nested-object", + query: `{ EntityWithAllTypes(where: {json: {_eq: {kind: "object", n: 1, nested: {a: [1, 2]}}}}, order_by: {id: asc}) { id } }`, + }, + { + // _cast casts the jsonb column to text, then applies a + // String_comparison_exp — a distinct code path (CompareOp::CastText) + // from every other jsonb operator above. + name: "wm-jsonb-cast-string-like", + query: `{ EntityWithAllTypes(where: {json: {_cast: {String: {_like: "%\\"kind\\"%"}}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "wm-jsonb-cast-string-eq-scalar", + query: `{ EntityWithAllTypes(where: {json: {_cast: {String: {_eq: "\\"just a string\\""}}}}, order_by: {id: asc}) { id } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/12-aggregate-matrix.ts b/packages/e2e-tests/src/differential/corpus/12-aggregate-matrix.ts new file mode 100644 index 0000000000..2cd830ba0e --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/12-aggregate-matrix.ts @@ -0,0 +1,255 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "am-token-numeric-full-matrix", + role: "admin", + query: `{ Token_aggregate { aggregate { count sum { tokenId } avg { tokenId } min { tokenId } max { tokenId } stddev { tokenId } stddev_pop { tokenId } stddev_samp { tokenId } var_pop { tokenId } var_samp { tokenId } variance { tokenId } } } }`, + }, + { + name: "am-user-int-full-matrix", + role: "admin", + query: `{ User_aggregate { aggregate { count sum { updatesCountOnUserForTesting } avg { updatesCountOnUserForTesting } min { updatesCountOnUserForTesting } max { updatesCountOnUserForTesting } stddev { updatesCountOnUserForTesting } stddev_pop { updatesCountOnUserForTesting } stddev_samp { updatesCountOnUserForTesting } var_pop { updatesCountOnUserForTesting } var_samp { updatesCountOnUserForTesting } variance { updatesCountOnUserForTesting } } } }`, + }, + { + name: "am-scalars-float8-full-matrix", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate(where: {id: {_in: ["scalar-1", "scalar-nulls", "scalar-unicode", "scalar-quotes", "scalar-empty"]}}) { aggregate { count sum { float_ } avg { float_ } min { float_ } max { float_ } stddev { float_ } stddev_pop { float_ } stddev_samp { float_ } var_pop { float_ } var_samp { float_ } variance { float_ } } } }`, + }, + { + name: "am-scalars-int-full-matrix", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { count sum { int_ } avg { int_ } min { int_ } max { int_ } stddev { int_ } stddev_pop { int_ } stddev_samp { int_ } var_pop { int_ } var_samp { int_ } variance { int_ } } } }`, + }, + { + name: "am-scalars-bigint-full-matrix", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { count sum { bigInt } avg { bigInt } min { bigInt } max { bigInt } stddev { bigInt } stddev_pop { bigInt } stddev_samp { bigInt } var_pop { bigInt } var_samp { bigInt } variance { bigInt } } } }`, + }, + { + name: "am-scalars-bigdecimal-full-matrix", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { count sum { bigDecimal bigDecimalWithConfig } avg { bigDecimal bigDecimalWithConfig } min { bigDecimal bigDecimalWithConfig } max { bigDecimal bigDecimalWithConfig } stddev { bigDecimal } var_samp { bigDecimalWithConfig } } } }`, + }, + { + name: "am-sim-int-full-matrix", + role: "admin", + query: `{ SimulateTestEvent_aggregate { aggregate { count sum { blockNumber logIndex timestamp } avg { blockNumber logIndex timestamp } min { blockNumber logIndex timestamp } max { blockNumber logIndex timestamp } stddev { logIndex } stddev_pop { logIndex } stddev_samp { logIndex } var_pop { timestamp } var_samp { timestamp } variance { timestamp } } } }`, + }, + { + name: "am-minmax-text-columns", + role: "admin", + query: `{ Token_aggregate { aggregate { min { id collection_id owner_id } max { id collection_id owner_id } } } }`, + }, + { + name: "am-minmax-text-unicode-empty", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { string optString } max { string optString } } } }`, + }, + { + name: "am-minmax-enum", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { enumField optEnumField } max { enumField optEnumField } } } }`, + }, + { + name: "am-minmax-timestamptz", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { timestamp optTimestamp } max { timestamp optTimestamp } } } }`, + }, + { + name: "am-minmax-user-mixed", + role: "admin", + query: `{ User_aggregate { aggregate { min { accountType address gravatar_id } max { accountType address gravatar_id } } } }`, + }, + { + name: "am-float8-sum-infinity-nan", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { sum { float_ } } } }`, + }, + { + name: "am-float8-minmax-infinity", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { float_ } max { float_ optFloat } } } }`, + }, + { + name: "am-float8-avg-nan", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { avg { optFloat } } } }`, + }, + { + name: "am-scalars-optint-null-handling", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { count(columns: optInt) sum { optInt } avg { optInt } min { optInt } max { optInt } } } }`, + }, + { + name: "am-empty-numeric-all-operators", + role: "admin", + query: `{ Token_aggregate(where: {id: {_eq: "missing"}}) { aggregate { count sum { tokenId } avg { tokenId } min { tokenId } max { tokenId } stddev { tokenId } stddev_pop { tokenId } stddev_samp { tokenId } var_pop { tokenId } var_samp { tokenId } variance { tokenId } } } }`, + }, + { + name: "am-empty-minmax-mixed-types", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate(where: {id: {_eq: "missing"}}) { aggregate { count min { id enumField timestamp int_ float_ } max { id enumField timestamp int_ float_ } } } }`, + }, + { + name: "am-empty-count-variants", + role: "admin", + query: `{ Token_aggregate(where: {id: {_eq: "missing"}}) { aggregate { count plain: count(columns: owner_id) dist: count(columns: owner_id, distinct: true) } } }`, + }, + { + name: "am-empty-with-nodes", + role: "admin", + query: `{ Token_aggregate(where: {id: {_eq: "missing"}}) { aggregate { count } nodes { id tokenId owner { id } } } }`, + }, + { + name: "am-single-row-stddev-null", + role: "admin", + query: `{ Token_aggregate(where: {id: {_eq: "tok-1"}}) { aggregate { count stddev { tokenId } stddev_pop { tokenId } stddev_samp { tokenId } var_pop { tokenId } var_samp { tokenId } variance { tokenId } } } }`, + }, + { + name: "am-count-multi-columns", + role: "admin", + query: `{ User_aggregate { aggregate { count(columns: [gravatar_id, accountType]) } } }`, + }, + { + name: "am-count-multi-columns-distinct", + role: "admin", + query: `{ Token_aggregate { aggregate { count(columns: [owner_id, collection_id], distinct: true) } } }`, + }, + { + name: "am-count-distinct-with-nulls", + role: "admin", + query: `{ User_aggregate { aggregate { total: count all: count(columns: gravatar_id) dist: count(columns: gravatar_id, distinct: true) } } }`, + }, + { + name: "am-count-distinct-no-nulls", + role: "admin", + query: `{ Token_aggregate { aggregate { total: count all: count(columns: owner_id) dist: count(columns: owner_id, distinct: true) } } }`, + }, + { + name: "am-count-distinct-no-columns", + role: "admin", + query: `{ User_aggregate { aggregate { count(distinct: true) } } }`, + }, + { + name: "am-nested-full-combo", + role: "admin", + query: `{ User(order_by: {id: asc}) { id tokens_aggregate(where: {tokenId: {_gte: 0}}, distinct_on: collection_id, order_by: [{collection_id: asc}, {tokenId: desc}], limit: 2, offset: 1) { aggregate { count sum { tokenId } min { tokenId } } nodes { id collection_id tokenId } } } }`, + }, + { + name: "am-nested-agg-empty-owner", + role: "admin", + query: `{ User_by_pk(id: "user-dangling") { id tokens_aggregate { aggregate { count sum { tokenId } avg { tokenId } min { tokenId } max { tokenId } } nodes { id } } } }`, + }, + { + name: "am-nested-count-distinct", + role: "admin", + query: `{ NftCollection(order_by: {id: asc}) { id tokens_aggregate { aggregate { count(columns: owner_id, distinct: true) } } } }`, + }, + { + name: "am-nested-agg-where-order-nodes", + role: "admin", + query: `{ NftCollection(order_by: {id: asc}) { id tokens_aggregate(where: {owner_id: {_like: "user-%"}}, order_by: {tokenId: asc}, limit: 3) { aggregate { count max { tokenId } } nodes { id tokenId } } } }`, + }, + { + name: "am-root-distinct-on-aggregate", + role: "admin", + query: `{ Token_aggregate(distinct_on: collection_id, order_by: [{collection_id: asc}, {id: asc}]) { aggregate { count sum { tokenId } } nodes { id collection_id } } }`, + }, + { + name: "am-raw-bigint-sum", + role: "admin", + query: `{ raw_events_aggregate { aggregate { sum { event_id serial } } } }`, + }, + { + name: "am-raw-bigint-avg-vs-int-avg", + role: "admin", + query: `{ raw_events_aggregate { aggregate { avg { event_id log_index } } } }`, + }, + { + name: "am-raw-bigint-minmax", + role: "admin", + query: `{ raw_events_aggregate { aggregate { min { event_id serial } max { event_id serial } } } }`, + }, + { + name: "am-raw-int-sum-overflows-int32", + role: "admin", + query: `{ raw_events_aggregate { aggregate { sum { chain_id block_number block_timestamp log_index } } } }`, + }, + { + name: "am-raw-bigint-stddev-variance", + role: "admin", + query: `{ raw_events_aggregate { aggregate { stddev { event_id } stddev_pop { event_id } var_pop { event_id } variance { event_id } } } }`, + }, + { + name: "am-raw-count-distinct-text-and-pair", + role: "admin", + query: `{ raw_events_aggregate { aggregate { hashes: count(columns: block_hash, distinct: true) pairs: count(columns: [chain_id, block_number], distinct: true) } } }`, + }, + { + name: "am-meta-float4-matrix", + role: "admin", + query: `{ _meta_aggregate { aggregate { count sum { eventsProcessed } avg { eventsProcessed } min { eventsProcessed } max { eventsProcessed } stddev { eventsProcessed } var_pop { eventsProcessed } } } }`, + }, + { + name: "am-meta-int-sum-nullable", + role: "admin", + query: `{ _meta_aggregate { aggregate { sum { endBlock firstEventBlock startBlock progressBlock } } } }`, + }, + { + name: "am-chainmeta-float4-matrix", + role: "admin", + query: `{ chain_metadata_aggregate { aggregate { count sum { num_events_processed } avg { num_events_processed } min { num_events_processed } max { num_events_processed } } } }`, + }, + { + name: "am-meta-minmax-timestamptz", + role: "admin", + query: `{ _meta_aggregate { aggregate { min { readyAt } max { readyAt } } } chain_metadata_aggregate { aggregate { min { timestamp_caught_up_to_head_or_endblock } max { timestamp_caught_up_to_head_or_endblock } } } }`, + }, + { + name: "am-user-avg-precision", + role: "admin", + query: `{ User_aggregate { aggregate { avg { updatesCountOnUserForTesting } } } }`, + }, + { + name: "am-agg-variables-where", + role: "admin", + query: `query ($w: Token_bool_exp) { Token_aggregate(where: $w) { aggregate { count sum { tokenId } } } }`, + variables: { w: { collection_id: { _eq: "coll-1" } } }, + }, + { + name: "am-error-min-bool", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { min { bool } } } }`, + }, + { + name: "am-error-sum-text-column", + role: "admin", + query: `{ Token_aggregate { aggregate { sum { id } } } }`, + }, + { + name: "am-error-avg-timestamp", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { avg { timestamp } } } }`, + }, + { + name: "am-error-variance-enum", + role: "admin", + query: `{ EntityWithAllNonArrayTypes_aggregate { aggregate { variance { enumField } } } }`, + }, + { + name: "am-error-count-unknown-column", + role: "admin", + query: `{ User_aggregate { aggregate { count(columns: [notAColumn]) } } }`, + }, + { + name: "am-error-sum-jsonb", + role: "admin", + query: `{ raw_events_aggregate { aggregate { sum { params } } } }`, + }, + { + name: "am-error-count-distinct-wrong-type", + role: "admin", + query: `{ User_aggregate { aggregate { count(distinct: "yes") } } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/13-order-distinct-matrix.ts b/packages/e2e-tests/src/differential/corpus/13-order-distinct-matrix.ts new file mode 100644 index 0000000000..0e62cba136 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/13-order-distinct-matrix.ts @@ -0,0 +1,223 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "om-order-text-asc", + query: `{ SimpleEntity(order_by: [{value: asc}, {id: asc}]) { id value } }`, + }, + { + name: "om-order-int-asc", + query: `{ User(order_by: [{updatesCountOnUserForTesting: asc}, {id: asc}]) { id updatesCountOnUserForTesting } }`, + }, + { + name: "om-order-int-desc", + query: `{ User(order_by: [{updatesCountOnUserForTesting: desc}, {id: asc}]) { id updatesCountOnUserForTesting } }`, + }, + { + name: "om-order-numeric-bigint-asc", + query: `{ EntityWithAllNonArrayTypes(order_by: [{bigInt: asc}, {id: asc}]) { id bigInt } }`, + }, + { + name: "om-order-numeric-bigdecimal-desc", + query: `{ EntityWithBigDecimal(order_by: [{bigDecimal: desc}, {id: asc}]) { id bigDecimal } }`, + }, + { + name: "om-order-bool-desc", + query: `{ EntityWithAllNonArrayTypes(order_by: [{bool: desc}, {id: asc}]) { id bool } }`, + }, + { + name: "om-order-enum-desc", + query: `{ Gravatar(order_by: [{size: desc}, {id: asc}]) { id size } }`, + }, + { + name: "om-order-timestamp-desc", + query: `{ EntityWithTimestamp(order_by: [{timestamp: desc}, {id: asc}]) { id timestamp } }`, + }, + { + name: "om-order-bigint-raw-events-asc", + query: `{ raw_events(order_by: [{event_id: asc}, {serial: asc}]) { serial chain_id event_id } }`, + }, + { + name: "om-order-bigint-raw-events-desc", + query: `{ raw_events(order_by: [{event_id: desc}, {serial: asc}]) { serial chain_id event_id } }`, + }, + { + // jsonb columns are orderable: PG jsonb btree order ranks + // Object > Array > Boolean > Number > String > Null. + name: "om-order-jsonb-asc", + query: `{ EntityWithAllTypes(order_by: [{json: asc}, {id: asc}]) { id json } }`, + }, + { + name: "om-order-jsonb-desc-raw-events", + query: `{ raw_events(order_by: [{params: desc}, {serial: asc}]) { serial params } }`, + }, + { + name: "om-order-float-special-desc", + query: `{ EntityWithAllNonArrayTypes(order_by: [{float_: desc}, {id: asc}]) { id float_ } }`, + }, + { + // PG sorts NaN greater than every other float, including Infinity, + // but null ordering still applies separately (asc defaults to nulls last). + name: "om-order-optfloat-nan-asc", + query: `{ EntityWithAllNonArrayTypes(order_by: [{optFloat: asc}, {id: asc}]) { id optFloat } }`, + }, + { + name: "om-order-optfloat-nan-desc-nulls-last", + query: `{ EntityWithAllNonArrayTypes(order_by: [{optFloat: desc_nulls_last}, {id: asc}]) { id optFloat } }`, + }, + { + name: "om-order-directions-opt-text", + query: `{ d1: User(order_by: [{gravatar_id: asc}, {id: asc}]) { id gravatar_id } d2: User(order_by: [{gravatar_id: desc}, {id: asc}]) { id gravatar_id } d3: User(order_by: [{gravatar_id: asc_nulls_first}, {id: asc}]) { id gravatar_id } d4: User(order_by: [{gravatar_id: asc_nulls_last}, {id: asc}]) { id gravatar_id } d5: User(order_by: [{gravatar_id: desc_nulls_first}, {id: asc}]) { id gravatar_id } d6: User(order_by: [{gravatar_id: desc_nulls_last}, {id: asc}]) { id gravatar_id } }`, + }, + { + name: "om-order-directions-opt-int", + query: `{ d1: EntityWithAllNonArrayTypes(order_by: [{optInt: asc}, {id: asc}]) { id optInt } d2: EntityWithAllNonArrayTypes(order_by: [{optInt: desc}, {id: asc}]) { id optInt } d3: EntityWithAllNonArrayTypes(order_by: [{optInt: asc_nulls_first}, {id: asc}]) { id optInt } d4: EntityWithAllNonArrayTypes(order_by: [{optInt: asc_nulls_last}, {id: asc}]) { id optInt } d5: EntityWithAllNonArrayTypes(order_by: [{optInt: desc_nulls_first}, {id: asc}]) { id optInt } d6: EntityWithAllNonArrayTypes(order_by: [{optInt: desc_nulls_last}, {id: asc}]) { id optInt } }`, + }, + { + name: "om-order-directions-opt-float", + query: `{ d1: EntityWithAllNonArrayTypes(order_by: [{optFloat: asc}, {id: asc}]) { id optFloat } d2: EntityWithAllNonArrayTypes(order_by: [{optFloat: desc}, {id: asc}]) { id optFloat } d3: EntityWithAllNonArrayTypes(order_by: [{optFloat: asc_nulls_first}, {id: asc}]) { id optFloat } d4: EntityWithAllNonArrayTypes(order_by: [{optFloat: asc_nulls_last}, {id: asc}]) { id optFloat } d5: EntityWithAllNonArrayTypes(order_by: [{optFloat: desc_nulls_first}, {id: asc}]) { id optFloat } d6: EntityWithAllNonArrayTypes(order_by: [{optFloat: desc_nulls_last}, {id: asc}]) { id optFloat } }`, + }, + { + name: "om-order-directions-opt-bigint", + query: `{ d1: EntityWithAllNonArrayTypes(order_by: [{optBigInt: asc}, {id: asc}]) { id optBigInt } d2: EntityWithAllNonArrayTypes(order_by: [{optBigInt: desc}, {id: asc}]) { id optBigInt } d3: EntityWithAllNonArrayTypes(order_by: [{optBigInt: asc_nulls_first}, {id: asc}]) { id optBigInt } d4: EntityWithAllNonArrayTypes(order_by: [{optBigInt: asc_nulls_last}, {id: asc}]) { id optBigInt } d5: EntityWithAllNonArrayTypes(order_by: [{optBigInt: desc_nulls_first}, {id: asc}]) { id optBigInt } d6: EntityWithAllNonArrayTypes(order_by: [{optBigInt: desc_nulls_last}, {id: asc}]) { id optBigInt } }`, + }, + { + name: "om-order-directions-opt-timestamp", + query: `{ d1: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: asc}, {id: asc}]) { id optTimestamp } d2: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: desc}, {id: asc}]) { id optTimestamp } d3: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: asc_nulls_first}, {id: asc}]) { id optTimestamp } d4: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: asc_nulls_last}, {id: asc}]) { id optTimestamp } d5: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: desc_nulls_first}, {id: asc}]) { id optTimestamp } d6: EntityWithAllNonArrayTypes(order_by: [{optTimestamp: desc_nulls_last}, {id: asc}]) { id optTimestamp } }`, + }, + { + name: "om-order-directions-opt-enum", + query: `{ d1: EntityWithAllNonArrayTypes(order_by: [{optEnumField: asc}, {id: asc}]) { id optEnumField } d2: EntityWithAllNonArrayTypes(order_by: [{optEnumField: desc}, {id: asc}]) { id optEnumField } d3: EntityWithAllNonArrayTypes(order_by: [{optEnumField: asc_nulls_first}, {id: asc}]) { id optEnumField } d4: EntityWithAllNonArrayTypes(order_by: [{optEnumField: asc_nulls_last}, {id: asc}]) { id optEnumField } d5: EntityWithAllNonArrayTypes(order_by: [{optEnumField: desc_nulls_first}, {id: asc}]) { id optEnumField } d6: EntityWithAllNonArrayTypes(order_by: [{optEnumField: desc_nulls_last}, {id: asc}]) { id optEnumField } }`, + }, + { + name: "om-order-multi-conflicting", + query: `{ SimulateTestEvent(order_by: [{blockNumber: asc}, {logIndex: desc}, {id: asc}]) { id blockNumber logIndex } }`, + }, + { + name: "om-order-multi-conflicting-flipped", + query: `{ SimulateTestEvent(order_by: [{blockNumber: desc}, {logIndex: asc}, {id: asc}]) { id blockNumber logIndex } }`, + }, + { + name: "om-order-multi-list-respects-order", + query: `{ SimulateTestEvent(order_by: [{logIndex: desc}, {blockNumber: asc}, {id: asc}]) { id blockNumber logIndex } }`, + }, + { + // Key order inside a single multi-key order_by object is NOT preserved: + // Hasura canonicalizes the keys, so this and the case below return the + // same rows, both differing from the list form above. + name: "om-order-object-keys-logindex-first", + query: `{ SimulateTestEvent(order_by: {logIndex: desc, blockNumber: asc, id: asc}) { id blockNumber logIndex } }`, + }, + { + name: "om-order-object-keys-blocknumber-first", + query: `{ SimulateTestEvent(order_by: {blockNumber: asc, logIndex: desc, id: asc}) { id blockNumber logIndex } }`, + }, + { + name: "om-order-mixed-list-with-multikey-object", + query: `{ SimulateTestEvent(order_by: [{blockNumber: desc, logIndex: desc}, {id: asc}]) { id blockNumber logIndex } }`, + }, + { + name: "om-order-same-column-twice-list", + query: `{ SimulateTestEvent(order_by: [{blockNumber: asc}, {blockNumber: desc}, {id: asc}]) { id blockNumber } }`, + }, + { + name: "om-order-object-rel-owner-id", + query: `{ Token(order_by: [{owner: {id: asc}}, {id: asc}]) { id owner { id } } }`, + }, + { + name: "om-order-object-rel-two-levels", + query: `{ Token(order_by: [{owner: {gravatar: {displayName: asc}}}, {id: asc}]) { id } }`, + }, + { + // Aggregate ordering through relationships is exposed regardless of the + // allow_aggregations permission; both phases pin that. + name: "om-order-object-rel-nested-aggregate", + query: `{ Token(order_by: [{collection: {tokens_aggregate: {count: asc}}}, {id: asc}]) { id collection_id } }`, + phases: ["default", "limited"], + }, + { + name: "om-order-array-rel-aggregate-count-desc", + query: `{ User(order_by: [{tokens_aggregate: {count: desc}}, {id: asc}]) { id } }`, + phases: ["default", "limited"], + }, + { + name: "om-order-array-rel-aggregate-max", + query: `{ User(order_by: [{tokens_aggregate: {max: {tokenId: desc}}}, {id: asc}]) { id } }`, + phases: ["default", "limited"], + }, + { + name: "om-introspect-user-order-by", + query: `{ __type(name: "User_order_by") { inputFields { name type { name kind } } } }`, + phases: ["default", "limited"], + }, + { + name: "om-introspect-token-aggregate-order-by", + query: `{ __type(name: "Token_aggregate_order_by") { inputFields { name type { name kind } } } }`, + phases: ["default", "limited"], + }, + { + name: "om-distinct-extra-order-keys", + query: `{ Token(distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}, {id: asc}]) { owner_id tokenId id } }`, + }, + { + name: "om-distinct-same-column-twice", + query: `{ Token(distinct_on: [owner_id, owner_id], order_by: [{owner_id: asc}, {id: asc}]) { owner_id id } }`, + }, + { + // The order_by prefix must contain the distinct_on columns but may list + // them in a different order. + name: "om-distinct-multi-prefix-swapped", + query: `{ SimulateTestEvent(distinct_on: [blockNumber, logIndex], order_by: [{logIndex: asc}, {blockNumber: asc}, {id: asc}]) { id blockNumber logIndex } }`, + }, + { + name: "om-distinct-no-order-by", + query: `{ Token(distinct_on: owner_id) { owner_id } }`, + compare: "rootSet", + }, + { + name: "om-order-by-empty-list", + query: `{ SimpleEntity(order_by: []) { id value } }`, + compare: "rootSet", + }, + { + name: "om-order-by-empty-object", + query: `{ SimpleEntity(order_by: {}) { id } }`, + compare: "rootSet", + }, + { + name: "om-order-by-null", + query: `{ SimpleEntity(order_by: null) { id } }`, + compare: "rootSet", + }, + { + name: "om-order-by-list-with-empty-object", + query: `{ SimpleEntity(order_by: [{}]) { id } }`, + compare: "rootSet", + }, + { + name: "om-order-by-variable-null", + query: `query ($ord: [SimpleEntity_order_by!]) { SimpleEntity(order_by: $ord) { id } }`, + variables: { ord: null }, + compare: "rootSet", + }, + { + name: "om-error-order-unknown-column", + query: `{ User(order_by: {bogus: asc}) { id } }`, + }, + { + name: "om-error-order-array-rel-column", + query: `{ User(order_by: {tokens: {tokenId: asc}}) { id } }`, + }, + { + name: "om-error-order-duplicate-key-in-object", + query: `{ SimulateTestEvent(order_by: {blockNumber: asc, blockNumber: desc}) { id } }`, + }, + { + name: "om-error-distinct-not-first-in-order", + query: `{ Token(distinct_on: owner_id, order_by: [{tokenId: asc}, {owner_id: asc}]) { id } }`, + }, + { + name: "om-error-distinct-unknown-column", + query: `{ Token(distinct_on: bogus) { id } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/14-variables-and-request.ts b/packages/e2e-tests/src/differential/corpus/14-variables-and-request.ts new file mode 100644 index 0000000000..1fd0c92401 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/14-variables-and-request.ts @@ -0,0 +1,256 @@ +import { defineCases } from "../corpus.js"; + +export default defineCases([ + { + name: "vr-var-string-where", + query: `query ($v: String!) { SimpleEntity(where: {value: {_eq: $v}}, order_by: {id: asc}) { id value } }`, + variables: { v: "v3" }, + }, + { + name: "vr-var-int-limit-offset", + query: `query ($l: Int!, $o: Int!) { SimpleEntity(order_by: {id: asc}, limit: $l, offset: $o) { id } }`, + variables: { l: 3, o: 2 }, + }, + { + name: "vr-var-float8-number", + query: `query ($f: float8!) { EntityWithAllNonArrayTypes(where: {float_: {_gt: $f}}, order_by: {id: asc}) { id float_ } }`, + variables: { f: 0.5 }, + }, + { + name: "vr-error-float8-variable-overflow", + query: `query ($f: float8!) { EntityWithAllNonArrayTypes(where: {float_: {_lt: $f}}, order_by: {id: asc}) { id } }`, + rawVariables: `{"f":1e400}`, + }, + { + // Hasura accepts a JSON string for a float8 variable. + name: "vr-var-float8-string-coerced", + query: `query ($f: float8!) { EntityWithAllNonArrayTypes(where: {float_: {_eq: $f}}, order_by: {id: asc}) { id float_ } }`, + variables: { f: "1.5" }, + }, + { + // A JSON string "true" coerces to boolean in a column comparison… + name: "vr-var-boolean-string-in-where-coerced", + query: `query ($b: Boolean!) { EntityWithAllNonArrayTypes(where: {bool: {_eq: $b}}, order_by: {id: asc}) { id bool } }`, + variables: { b: "true" }, + }, + { + // …but the same string is rejected when used in a directive's if. + name: "vr-error-boolean-string-in-include-directive", + query: `query ($b: Boolean!) { SimpleEntity(order_by: {id: asc}, limit: 1) { id value @include(if: $b) } }`, + variables: { b: "true" }, + }, + { + name: "vr-var-numeric-as-string", + query: `query ($n: numeric!) { Token(where: {tokenId: {_eq: $n}}, order_by: {id: asc}) { id tokenId } }`, + variables: { n: "1000000000000000000000000000000" }, + }, + { + name: "vr-var-numeric-as-number", + query: `query ($n: numeric!) { Token(where: {tokenId: {_eq: $n}}, order_by: {id: asc}) { id tokenId } }`, + variables: { n: 8 }, + }, + { + name: "vr-var-numeric-decimal-number", + query: `query ($n: numeric!) { EntityWithAllNonArrayTypes(where: {bigDecimal: {_eq: $n}}, order_by: {id: asc}) { id bigDecimal } }`, + variables: { n: 1.25 }, + }, + { + name: "vr-var-numeric-overflow-number", + query: `query ($n: numeric!) { Token(where: {tokenId: {_eq: $n}}, order_by: {id: asc}) { id tokenId } }`, + rawVariables: `{"n":1e400}`, + }, + { + name: "vr-var-jsonb-nested-overflow-number", + query: `query ($j: jsonb!) { EntityWithAllTypes(where: {json: {_contains: $j}}, order_by: {id: asc}) { id } }`, + rawVariables: `{"j":{"nested":-9e999}}`, + }, + { + name: "vr-var-timestamptz-string", + query: `query ($ts: timestamptz!) { EntityWithTimestamp(where: {timestamp: {_eq: $ts}}, order_by: {id: asc}) { id timestamp } }`, + variables: { ts: "2024-01-15T12:34:56.123456+00:00" }, + }, + { + name: "vr-var-enum-scalar-accounttype", + query: `query ($t: accounttype!) { User(where: {accountType: {_eq: $t}}, order_by: {id: asc}) { id accountType } }`, + variables: { t: "ADMIN" }, + }, + { + // Passes GraphQL validation (accounttype is a scalar) and fails in + // Postgres with a data-exception. + name: "vr-error-enum-scalar-invalid-value", + query: `query ($t: accounttype!) { User(where: {accountType: {_eq: $t}}, order_by: {id: asc}) { id } }`, + variables: { t: "SUPERADMIN" }, + }, + { + name: "vr-var-jsonb-object-contains", + query: `query ($j: jsonb!) { EntityWithAllTypes(where: {json: {_contains: $j}}, order_by: {id: asc}) { id json } }`, + variables: { j: { kind: "object" } }, + }, + { + name: "vr-var-jsonb-unicode-contains", + query: `query ($j: jsonb!) { EntityWithAllTypes(where: {json: {_contains: $j}}, order_by: {id: asc}) { id } }`, + variables: { j: { héllo: "wörld 🚀" } }, + }, + { + name: "vr-var-string-list-in", + query: `query ($ids: [String!]!) { SimpleEntity(where: {id: {_in: $ids}}, order_by: {id: asc}) { id } }`, + variables: { ids: ["simple-1", "simple-9", "missing"] }, + }, + { + name: "vr-var-string-list-single-value-coercion", + query: `query ($ids: [String!]!) { SimpleEntity(where: {id: {_in: $ids}}, order_by: {id: asc}) { id } }`, + variables: { ids: "simple-1" }, + }, + { + name: "vr-error-string-list-int-element", + query: `query ($ids: [String!]!) { SimpleEntity(where: {id: {_in: $ids}}, order_by: {id: asc}) { id } }`, + variables: { ids: 5 }, + }, + { + name: "vr-var-bool-exp-token", + query: `query ($w: Token_bool_exp!) { Token(where: $w, order_by: {id: asc}) { id tokenId } }`, + variables: { w: { tokenId: { _gte: 7 } } }, + }, + { + name: "vr-var-order-by-list", + query: `query ($ord: [Token_order_by!]!) { Token(order_by: $ord, limit: 4) { id tokenId owner_id } }`, + variables: { ord: [{ owner_id: "asc" }, { tokenId: "desc" }, { id: "asc" }] }, + }, + { + name: "vr-var-order-by-enum-in-object-default", + query: `query ($dir: order_by = desc) { SimpleEntity(order_by: [{id: $dir}]) { id } }`, + }, + { + name: "vr-var-select-column-distinct-on", + query: `query ($cols: [Token_select_column!]!) { Token(distinct_on: $cols, order_by: [{owner_id: asc}, {tokenId: desc}, {id: asc}]) { id owner_id } }`, + variables: { cols: ["owner_id"] }, + }, + { + name: "vr-var-select-column-single-value-coercion", + query: `query ($cols: [Token_select_column!]!) { Token(distinct_on: $cols, order_by: [{collection_id: asc}, {tokenId: desc}, {id: asc}]) { id collection_id } }`, + variables: { cols: "collection_id" }, + }, + { + name: "vr-var-nested-relationship-args", + query: `query ($tw: Token_bool_exp, $tl: Int, $tord: [Token_order_by!]) { User(order_by: {id: asc}) { id tokens(where: $tw, limit: $tl, order_by: $tord) { id tokenId } } }`, + variables: { + tw: { tokenId: { _gte: 0 } }, + tl: 2, + tord: [{ tokenId: "desc" }, { id: "asc" }], + }, + }, + { + name: "vr-default-bool-exp-used", + query: `query ($w: SimpleEntity_bool_exp = {id: {_eq: "simple-2"}}) { SimpleEntity(where: $w, order_by: {id: asc}) { id value } }`, + }, + { + name: "vr-default-int-overridden", + query: `query ($lim: Int = 2) { SimpleEntity(order_by: {id: asc}, limit: $lim) { id } }`, + variables: { lim: 1 }, + }, + { + name: "vr-default-null-override", + query: `query ($lim: Int = 2) { SimpleEntity(order_by: {id: asc}, limit: $lim) { id } }`, + variables: { lim: null }, + }, + { + name: "vr-var-missing-variables-object", + query: `query ($w: SimpleEntity_bool_exp) { SimpleEntity(where: $w, order_by: {id: asc}) { id } }`, + }, + { + name: "vr-var-null-for-nullable-args", + query: `query ($w: SimpleEntity_bool_exp, $l: Int) { SimpleEntity(where: $w, limit: $l, order_by: {id: asc}) { id } }`, + variables: { w: null, l: null }, + }, + { + name: "vr-error-int-var-float-json", + query: `query ($l: Int!) { SimpleEntity(order_by: {id: asc}, limit: $l) { id } }`, + variables: { l: 1.5 }, + }, + { + name: "vr-error-int-var-string-json", + query: `query ($l: Int!) { SimpleEntity(order_by: {id: asc}, limit: $l) { id } }`, + variables: { l: "1" }, + }, + { + name: "vr-error-numeric-var-bool", + query: `query ($n: numeric!) { Token(where: {tokenId: {_eq: $n}}, order_by: {id: asc}) { id } }`, + variables: { n: true }, + }, + { + name: "vr-error-extra-undeclared-variable", + query: `query ($l: Int) { SimpleEntity(order_by: {id: asc}, limit: $l) { id } }`, + variables: { l: 2, extraneous: "ignored", another: 5 }, + }, + { + name: "vr-error-id-type-variable", + query: `query ($id: ID!) { User_by_pk(id: $id) { id } }`, + variables: { id: "user-1" }, + }, + { + name: "vr-error-opname-with-anonymous-op", + query: `query A { SimpleEntity(order_by: {id: asc}, limit: 1) { id } } { User(order_by: {id: asc}, limit: 1) { id } }`, + operationName: "A", + }, + { + name: "vr-opname-selects-op-with-vars", + query: `query WithVar($v: String!) { SimpleEntity(where: {value: {_eq: $v}}, order_by: {id: asc}) { id value } } query NoVar { User(order_by: {id: asc}, limit: 1) { id } }`, + operationName: "WithVar", + variables: { v: "v2" }, + }, + { + // Only the selected operation is validated: the mutation would be + // invalid for the public role, yet the query still runs. + name: "vr-opname-query-beside-mutation-public", + query: `query Q { SimpleEntity(order_by: {id: asc}, limit: 1) { id } } mutation M { insert_Bogus(objects: []) { affected_rows } }`, + operationName: "Q", + }, + { + name: "vr-admin-mutation-insert-unknown-table", + role: "admin", + query: `mutation { insert_Bogus(objects: []) { affected_rows } }`, + }, + // envio serve is a read-only server: Hasura's admin mutation surface is + // deliberately out of scope, so only mutation cases whose responses don't + // depend on mutation types existing (unknown-table errors) are kept. + { + name: "vr-directive-include-fragment-spread", + query: `query ($inc: Boolean!) { User(order_by: {id: asc}, limit: 2) { id ...Extra @include(if: $inc) } } fragment Extra on User { address accountType }`, + variables: { inc: true }, + }, + { + name: "vr-directive-include-fragment-spread-false", + query: `query ($inc: Boolean!) { User(order_by: {id: asc}, limit: 2) { id ...Extra @include(if: $inc) } } fragment Extra on User { address accountType }`, + variables: { inc: false }, + }, + { + name: "vr-directive-skip-inline-fragment", + query: `query ($skip: Boolean!) { User(order_by: {id: asc}, limit: 2) { id ... on User @skip(if: $skip) { address } } }`, + variables: { skip: true }, + }, + { + name: "vr-error-directive-include-on-operation", + query: `query Q @include(if: true) { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }`, + }, + { + name: "vr-alias-duplicate-root-different-args", + query: `{ few: SimpleEntity(order_by: {id: asc}, limit: 2) { id } more: SimpleEntity(order_by: {id: desc}, limit: 3) { id value } one: SimpleEntity_by_pk(id: "simple-5") { id } miss: SimpleEntity_by_pk(id: "nope") { id } }`, + }, + { + name: "vr-error-same-alias-conflicting-args", + query: `{ x: SimpleEntity(order_by: {id: asc}, limit: 1) { id } x: SimpleEntity(order_by: {id: desc}, limit: 1) { id } }`, + }, + { + name: "vr-fragment-chain-deep", + query: `fragment L1 on User { id ...L2 } fragment L2 on User { gravatar { ...L3 } } fragment L3 on Gravatar { id owner { ...L4 } } fragment L4 on User { address tokens(order_by: {id: asc}, limit: 1) { ...L5 } } fragment L5 on Token { id tokenId } { User(order_by: {id: asc}) { ...L1 } }`, + }, + { + name: "vr-typename-nested-everywhere", + query: `{ User(order_by: {id: asc}) { __typename id gravatar { __typename id } tokens(order_by: {id: asc}) { __typename id collection { __typename id } } } }`, + }, + { + name: "vr-typename-aggregate-admin", + role: "admin", + query: `{ Token_aggregate(order_by: {id: asc}) { __typename aggregate { __typename count sum { __typename tokenId } } nodes { __typename id } } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/15-scalar-serialization.ts b/packages/e2e-tests/src/differential/corpus/15-scalar-serialization.ts new file mode 100644 index 0000000000..37b151ada5 --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/15-scalar-serialization.ts @@ -0,0 +1,147 @@ +import { defineCases } from "../corpus.js"; + +// Full column lists in schema order, so each per-row case pins every value of +// that row in isolation. +const nonArrayCols = `id string optString int_ optInt float_ optFloat bool optBool bigInt optBigInt bigDecimal optBigDecimal bigDecimalWithConfig enumField optEnumField timestamp optTimestamp`; +const allTypesCols = `id string optString arrayOfStrings int_ optInt arrayOfInts float_ optFloat arrayOfFloats bool optBool bigInt optBigInt arrayOfBigInts bigDecimal optBigDecimal bigDecimalWithConfig arrayOfBigDecimals timestamp optTimestamp json enumField optEnumField`; +const precisionCols = `id exampleBigInt exampleBigIntRequired exampleBigIntArray exampleBigIntArrayRequired exampleBigDecimal exampleBigDecimalRequired exampleBigDecimalArray exampleBigDecimalArrayRequired exampleBigDecimalOtherOrder`; + +const nonArrayRow = (name: string, id: string) => ({ + name, + query: `{ EntityWithAllNonArrayTypes_by_pk(id: "${id}") { ${nonArrayCols} } }`, +}); +const allTypesRow = (name: string, id: string) => ({ + name, + query: `{ EntityWithAllTypes_by_pk(id: "${id}") { ${allTypesCols} } }`, +}); +const precisionRow = (name: string, id: string) => ({ + name, + query: `{ PostgresNumericPrecisionEntityTester_by_pk(id: "${id}") { ${precisionCols} } }`, +}); +const bigDecimalRow = (name: string, id: string) => ({ + name, + query: `{ EntityWithBigDecimal_by_pk(id: "${id}") { id bigDecimal } }`, +}); +const timestampRow = (name: string, id: string) => ({ + name, + query: `{ EntityWithTimestamp_by_pk(id: "${id}") { id timestamp } }`, +}); + +export default defineCases([ + nonArrayRow("ss-row-nonarray-scalar-1", "scalar-1"), + nonArrayRow("ss-row-nonarray-scalar-nulls", "scalar-nulls"), + nonArrayRow("ss-row-nonarray-scalar-extremes", "scalar-extremes"), + nonArrayRow("ss-row-nonarray-scalar-special-float", "scalar-special-float"), + nonArrayRow("ss-row-nonarray-scalar-neg-inf", "scalar-neg-inf"), + nonArrayRow("ss-row-nonarray-scalar-unicode", "scalar-unicode"), + nonArrayRow("ss-row-nonarray-scalar-quotes", "scalar-quotes"), + nonArrayRow("ss-row-nonarray-scalar-empty", "scalar-empty"), + allTypesRow("ss-row-alltypes-all-1", "all-1"), + allTypesRow("ss-row-alltypes-all-empty-arrays", "all-empty-arrays"), + allTypesRow("ss-row-alltypes-all-array-edge", "all-array-edge"), + allTypesRow("ss-row-alltypes-all-json-string", "all-json-string"), + allTypesRow("ss-row-alltypes-all-json-number", "all-json-number"), + allTypesRow("ss-row-alltypes-all-json-null", "all-json-null"), + allTypesRow("ss-row-alltypes-all-json-unicode", "all-json-unicode"), + allTypesRow("ss-row-alltypes-all-json-bool", "all-json-bool"), + precisionRow("ss-row-precision-prec-1", "prec-1"), + precisionRow("ss-row-precision-prec-nulls", "prec-nulls"), + precisionRow("ss-row-precision-prec-2", "prec-2"), + bigDecimalRow("ss-row-bigdecimal-bd-1", "bd-1"), + bigDecimalRow("ss-row-bigdecimal-bd-2", "bd-2"), + bigDecimalRow("ss-row-bigdecimal-bd-3", "bd-3"), + bigDecimalRow("ss-row-bigdecimal-bd-4", "bd-4"), + bigDecimalRow("ss-row-bigdecimal-bd-5", "bd-5"), + timestampRow("ss-row-timestamp-ts-epoch", "ts-epoch"), + timestampRow("ss-row-timestamp-ts-micro", "ts-micro"), + timestampRow("ss-row-timestamp-ts-milli", "ts-milli"), + timestampRow("ss-row-timestamp-ts-pre-epoch", "ts-pre-epoch"), + timestampRow("ss-row-timestamp-ts-future", "ts-future"), + timestampRow("ss-row-timestamp-ts-zoned", "ts-zoned"), + { + // numeric(n,s)[] elements stay raw JSON numbers (trailing zeros intact) + // even though STRINGIFY_NUMERIC_TYPES turns numeric scalars into strings. + name: "ss-arrays-numeric-precision-string-vs-number", + query: `{ PostgresNumericPrecisionEntityTester(order_by: {id: asc}) { id exampleBigInt exampleBigIntArray exampleBigIntArrayRequired exampleBigDecimal exampleBigDecimalArray exampleBigDecimalArrayRequired } }`, + }, + { + name: "ss-arrays-alltypes-string-vs-number", + query: `{ EntityWithAllTypes(order_by: {id: asc}) { id arrayOfInts float_ arrayOfFloats bigInt arrayOfBigInts bigDecimal arrayOfBigDecimals } }`, + }, + { + name: "ss-json-path-key", + query: `{ EntityWithAllTypes_by_pk(id: "all-1") { id json(path: "$.kind") } }`, + }, + { + name: "ss-json-path-root-index", + query: `{ EntityWithAllTypes_by_pk(id: "all-array-edge") { id json(path: "$[0]") } }`, + }, + { + name: "ss-json-path-nested-index", + query: `{ EntityWithAllTypes_by_pk(id: "all-1") { id json(path: "$.nested.a[1]") } }`, + }, + { + name: "ss-json-path-missing-nested", + query: `{ EntityWithAllTypes_by_pk(id: "all-1") { id json(path: "$.nested.missing.deep") } }`, + }, + { + name: "ss-json-path-on-scalar-value", + query: `{ EntityWithAllTypes_by_pk(id: "all-json-string") { id json(path: "$.anything") } }`, + }, + { + name: "ss-json-path-on-json-null", + query: `{ EntityWithAllTypes_by_pk(id: "all-json-null") { id json(path: "$.x") } }`, + }, + { + // "$" returns the whole document in jsonb key order, not insertion order. + name: "ss-json-path-dollar-root", + query: `{ EntityWithAllTypes_by_pk(id: "all-1") { id json(path: "$") } }`, + }, + { + // Hasura accepts paths without the leading "$." prefix. + name: "ss-json-path-no-dollar-prefix", + query: `{ EntityWithAllTypes_by_pk(id: "all-1") { id json(path: "kind") } }`, + }, + { + name: "ss-json-path-unicode-key", + query: `{ EntityWithAllTypes_by_pk(id: "all-json-unicode") { id json(path: "$.héllo") } }`, + }, + { + name: "ss-json-path-empty-string-error", + query: `{ EntityWithAllTypes_by_pk(id: "all-1") { id json(path: "") } }`, + }, + { + name: "ss-json-path-variable", + query: `query ($p: String) { EntityWithAllTypes_by_pk(id: "all-1") { id json(path: $p) } }`, + variables: { p: "$.nested.a" }, + }, + { + name: "ss-json-alias-three-paths", + query: `{ EntityWithAllTypes_by_pk(id: "all-1") { id whole: json(path: "$") kind: json(path: "$.kind") second: json(path: "$.nested.a[0]") } }`, + }, + { + name: "ss-bypk-special-chars-full", + query: `{ User_by_pk(id: "user \\"quoted\\" 🚀") { id address gravatar_id updatesCountOnUserForTesting accountType } }`, + }, + { + name: "ss-bypk-special-chars-variable", + query: `query ($id: String!) { User_by_pk(id: $id) { id address accountType } }`, + variables: { id: 'user "quoted" 🚀' }, + }, + { + name: "ss-typename-only-list", + query: `{ EntityWithBigDecimal(order_by: {id: asc}) { __typename } }`, + }, + { + name: "ss-typename-only-by-pk", + query: `{ PostgresNumericPrecisionEntityTester_by_pk(id: "prec-1") { __typename } }`, + }, + { + name: "ss-field-order-reverse-schema", + query: `{ EntityWithAllNonArrayTypes_by_pk(id: "scalar-1") { optTimestamp timestamp optEnumField enumField bigDecimalWithConfig optBigDecimal bigDecimal optBigInt bigInt optBool bool optFloat float_ optInt int_ optString string id } }`, + }, + { + name: "ss-field-order-interleaved", + query: `{ EntityWithAllTypes_by_pk(id: "all-1") { json bool __typename bigDecimal id enumField arrayOfInts } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/16-relationship-matrix.ts b/packages/e2e-tests/src/differential/corpus/16-relationship-matrix.ts new file mode 100644 index 0000000000..e6b951ee0f --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/16-relationship-matrix.ts @@ -0,0 +1,230 @@ +import { defineCases } from "../corpus.js"; + +// Relationship edge matrix: existence filters ({rel: {}} / _not: {rel: {}}), +// dangling FKs for every object relationship in the fixture, multi-hop +// A→B→C→D traversals, cross-boundary boolean logic, child selection args +// combined, aggregate ordering with nulls, and alias/column shadowing. +export default defineCases([ + // ── array-rel existence: {rel: {}} = has any, _not: {rel: {}} = has none ── + { + name: "rm-exists-user-tokens-pair", + query: `{ any: User(where: {tokens: {}}, order_by: {id: asc}) { id } none: User(where: {_not: {tokens: {}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "rm-exists-collection-tokens-pair", + query: `{ any: NftCollection(where: {tokens: {}}, order_by: {id: asc}) { id name } none: NftCollection(where: {_not: {tokens: {}}}, order_by: {id: asc}) { id name } }`, + }, + { + name: "rm-exists-b-a-pair", + query: `{ any: B(where: {a: {}}, order_by: {id: asc}) { id } none: B(where: {_not: {a: {}}}, order_by: {id: asc}) { id } }`, + }, + { + // The `none` root is deliberately empty: every D row with a live c + // reference makes its C non-empty, and dangling d-4 belongs to no C. + name: "rm-exists-c-d-pair", + query: `{ any: C(where: {d: {}}, order_by: {id: asc}) { id } none: C(where: {_not: {d: {}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "rm-exists-bare-vs-predicate", + query: `{ bare: NftCollection(where: {tokens: {}}, order_by: {id: asc}) { id } withPred: NftCollection(where: {tokens: {tokenId: {_gt: 1000}}}, order_by: {id: asc}) { id } }`, + }, + { + // Hasura v2.43 accepts multiple count arguments in the schema but emits + // count(col1, col2), so PostgreSQL returns a database-query error. Keep + // this live case to prevent an accidental API divergence. + name: "rm-aggregate-predicate-multi-column-count", + phases: ["limited"], + query: `{ allRows: NftCollection(where: {tokens_aggregate: {count: {arguments: [owner_id, collection_id], distinct: false, predicate: {_gt: 0}}}}, order_by: {id: asc}) { id } distinctPairs: NftCollection(where: {tokens_aggregate: {count: {arguments: [owner_id, collection_id], distinct: true, predicate: {_gt: 1}}}}, order_by: {id: asc}) { id } }`, + }, + + // ── object-rel existence vs FK null-ness ───────────────────────────── + { + name: "rm-object-exists-gravatar-pair", + query: `{ has: User(where: {gravatar: {}}, order_by: {id: asc}) { id gravatar_id } lacks: User(where: {_not: {gravatar: {}}}, order_by: {id: asc}) { id gravatar_id } }`, + }, + { + // user-dangling has a non-null gravatar_id pointing nowhere, so it is in + // fkNotNull but not in exists. + name: "rm-object-exists-vs-fk-not-null", + query: `{ exists: User(where: {gravatar: {}}, order_by: {id: asc}) { id } fkNotNull: User(where: {gravatar_id: {_is_null: false}}, order_by: {id: asc}) { id } }`, + }, + { + name: "rm-object-not-exists-token-owner", + query: `{ Token(where: {_not: {owner: {}}}, order_by: {id: asc}) { id owner_id } }`, + }, + { + name: "rm-object-not-exists-token-collection", + query: `{ Token(where: {_not: {collection: {}}}, order_by: {id: asc}) { id collection_id } }`, + }, + { + name: "rm-object-not-exists-gravatar-owner", + query: `{ Gravatar(where: {_not: {owner: {}}}, order_by: {id: asc}) { id owner_id } }`, + }, + { + // b-2 (NULL c_id) and b-3 (dangling c_id) both count as "no c". + name: "rm-object-not-exists-b-c", + query: `{ B(where: {_not: {c: {}}}, order_by: {id: asc}) { id c_id } }`, + }, + { + name: "rm-object-exists-a-b-pair", + query: `{ has: A(where: {b: {}}, order_by: {id: asc}) { id b_id } lacks: A(where: {_not: {b: {}}}, order_by: {id: asc}) { id b_id } }`, + }, + + // ── dangling FK output shape for every object relationship ─────────── + { + name: "rm-dangling-token-collection", + query: `{ Token_by_pk(id: "tok-7") { id collection_id collection { id name } } }`, + }, + { + name: "rm-dangling-token-owner", + query: `{ Token_by_pk(id: "tok-6") { id owner_id owner { id address } } }`, + }, + { + name: "rm-dangling-gravatar-owner", + query: `{ Gravatar_by_pk(id: "grav-3") { id owner_id owner { id address } } }`, + }, + { + name: "rm-dangling-user-gravatar", + query: `{ User_by_pk(id: "user-dangling") { id gravatar_id gravatar { id displayName } } }`, + }, + { + name: "rm-dangling-b-c-all-rows", + query: `{ B(order_by: {id: asc}) { id c_id c { id stringThatIsMirroredToA } } }`, + }, + { + name: "rm-dangling-a-b", + query: `{ A_by_pk(id: "a-4") { id b_id b { id c_id } } }`, + }, + { + // d-4 references c-missing: reachable through its plain text column but + // through no C.d relationship. + name: "rm-dangling-d-via-rel-vs-column", + query: `{ viaRel: C(where: {d: {id: {_eq: "d-4"}}}, order_by: {id: asc}) { id } viaColumn: D(where: {c: {_eq: "c-missing"}}, order_by: {id: asc}) { id c } }`, + }, + + // ── multi-hop A→B→C→D traversals ───────────────────────────────────── + { + name: "rm-multihop-a-b-c-d", + query: `{ A(order_by: {id: asc}) { id optionalStringToTestLinkedEntities b { id c { id stringThatIsMirroredToA d(order_by: {id: asc}) { id c } } } } }`, + }, + { + name: "rm-multihop-c-both-directions", + query: `{ C(order_by: {id: asc}) { id a { id b { id c { id } } } d(order_by: {id: asc}) { id } } }`, + }, + { + name: "rm-multihop-b-both-directions", + query: `{ B(order_by: {id: asc}) { id a(order_by: {id: asc}) { id b { id } } c { id d(order_by: {id: asc}) { id } } } }`, + }, + { + // In D_bool_exp `c` is a plain String comparison, not a relationship. + name: "rm-multihop-d-plain-column-filter", + query: `{ C(where: {d: {c: {_eq: "c-1"}}}, order_by: {id: asc}) { id d(where: {c: {_eq: "c-1"}}, order_by: {id: asc}) { id c } } }`, + }, + { + name: "rm-multihop-a-b-a-siblings", + query: `{ A(order_by: {id: asc}) { id b { id a(order_by: {id: asc}) { id } } } }`, + }, + + // ── array rel with where + distinct_on + order_by + limit + offset ─── + { + name: "rm-child-all-args-user-tokens", + query: `{ User(order_by: {id: asc}) { id tokens(where: {tokenId: {_gte: 0}}, distinct_on: collection_id, order_by: [{collection_id: asc}, {tokenId: desc}, {id: asc}], limit: 2, offset: 1) { id collection_id tokenId } } }`, + }, + { + name: "rm-child-all-args-collection-tokens", + query: `{ NftCollection(order_by: {id: asc}) { id tokens(where: {owner: {accountType: {_eq: "USER"}}}, distinct_on: owner_id, order_by: [{owner_id: asc}, {tokenId: desc}, {id: asc}], limit: 2, offset: 1) { id owner_id tokenId } } }`, + }, + { + // Deliberately empty child arrays: offset beyond every child row set. + name: "rm-child-window-beyond-rows", + query: `{ User(where: {id: {_in: ["user-1", "user-2"]}}, order_by: {id: asc}) { id tokens(order_by: {id: asc}, limit: 3, offset: 50) { id } } }`, + }, + + // ── _and/_or/_not spanning the relationship boundary ───────────────── + { + name: "rm-cross-and-parent-child", + query: `{ User(where: {_and: [{accountType: {_eq: "ADMIN"}}, {tokens: {collection: {symbol: {_eq: "ALPHA"}}}}]}, order_by: {id: asc}) { id } }`, + }, + { + name: "rm-cross-or-three-branches", + query: `{ Token(where: {_or: [{tokenId: {_lt: 0}}, {owner: {accountType: {_eq: "ADMIN"}}}, {collection: {name: {_eq: ""}}}]}, order_by: {id: asc}) { id tokenId owner_id collection_id } }`, + }, + { + // Users owning a token whose collection row is missing (tok-7). + name: "rm-cross-not-inside-rel", + query: `{ User(where: {tokens: {_not: {collection: {}}}}, order_by: {id: asc}) { id } }`, + }, + { + name: "rm-cross-and-inside-rel", + query: `{ User(where: {tokens: {_and: [{tokenId: {_gte: 0}}, {collection: {symbol: {_eq: "BÉTA"}}}]}}, order_by: {id: asc}) { id } }`, + }, + { + name: "rm-cross-or-two-rel-paths", + query: `{ User(where: {_or: [{gravatar: {size: {_eq: "MEDIUM"}}}, {tokens: {tokenId: {_eq: "9999999999999999999999999999999999999999999999999999999999999999999999999999"}}}]}, order_by: {id: asc}) { id } }`, + }, + + // ── same table reached via different relationship paths ────────────── + { + name: "rm-same-table-two-paths", + query: `{ User(where: {tokens: {collection: {tokens: {owner: {accountType: {_eq: "USER"}}}}}}, order_by: {id: asc}) { id } }`, + }, + { + // ADMIN-owned tokens whose collection also holds a USER-owned sibling. + name: "rm-same-table-token-and-sibling", + query: `{ Token(where: {_and: [{owner: {accountType: {_eq: "ADMIN"}}}, {collection: {tokens: {owner: {accountType: {_eq: "USER"}}}}}]}, order_by: {id: asc}) { id owner_id collection_id } }`, + }, + { + name: "rm-same-table-b-self-join", + query: `{ A(where: {b: {a: {id: {_eq: "a-2"}}}}, order_by: {id: asc}) { id b_id } }`, + }, + + // ── self-referential deep nesting ──────────────────────────────────── + { + name: "rm-deep-self-nesting-depth7", + query: `{ User(where: {id: {_eq: "user-1"}}) { id tokens(order_by: {id: asc}, limit: 2) { id owner { id tokens(order_by: {id: asc}, limit: 2) { id owner { id tokens(order_by: {id: asc}, limit: 2) { id tokenId owner { id } } } } } } } }`, + }, + { + name: "rm-deep-where-self-referential", + query: `{ User(where: {tokens: {owner: {tokens: {owner: {tokens: {tokenId: {_eq: "8"}}}}}}}, order_by: {id: asc}) { id } }`, + }, + + // ── parent ordered by child aggregate, with nulls from empty sets ──── + { + // coll-3 has no tokens, so its max is NULL and sorts first. + name: "rm-agg-order-max-nulls-first", + query: `{ NftCollection(order_by: [{tokens_aggregate: {max: {tokenId: asc_nulls_first}}}, {id: asc}]) { id } }`, + }, + { + name: "rm-agg-order-count-asc-empty-first", + query: `{ NftCollection(order_by: [{tokens_aggregate: {count: asc}}, {id: asc}]) { id currentSupply } }`, + }, + { + name: "rm-agg-order-sum-desc-nulls-last", + query: `{ User(order_by: [{tokens_aggregate: {sum: {tokenId: desc_nulls_last}}}, {id: asc}]) { id } }`, + }, + { + name: "rm-agg-order-min-asc-nulls-first", + query: `{ User(order_by: [{tokens_aggregate: {min: {tokenId: asc_nulls_first}}}, {id: asc}]) { id } }`, + }, + { + // tok-7's dangling collection yields a NULL join, sorting first. + name: "rm-order-object-rel-dangling-nulls-first", + query: `{ Token(order_by: [{collection: {name: asc_nulls_first}}, {id: asc}]) { id collection_id } }`, + }, + + // ── alias shadowing between relationships and columns ──────────────── + { + name: "rm-alias-swap-column-and-rel", + query: `{ Token(order_by: {id: asc}, limit: 4) { id owner: owner_id owner_id: owner { id } collection: collection_id collection_id: collection { id name } } }`, + }, + { + name: "rm-alias-user-gravatar-shadow", + query: `{ User(order_by: {id: asc}, limit: 3) { id gravatar: gravatar_id gravatar_id: gravatar { id displayName } tokens: address address: tokens(order_by: {id: asc}, limit: 1) { id } } }`, + }, + { + // Field-merge conflict: response key "owner" bound to both the scalar + // owner_id column and the owner relationship. + name: "rm-alias-conflict-rel-vs-column", + query: `{ Token(limit: 1) { owner: owner_id owner { id } } }`, + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/17-error-matrix.ts b/packages/e2e-tests/src/differential/corpus/17-error-matrix.ts new file mode 100644 index 0000000000..9ea4b6d93d --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/17-error-matrix.ts @@ -0,0 +1,206 @@ +import { defineCases } from "../corpus.js"; + +const deepGravatarOwner = (levels: number): string => { + let sel = "id"; + for (let i = 0; i < levels; i++) sel = `id gravatar { id owner { ${sel} } }`; + return sel; +}; + +export default defineCases([ + // ── arguments of the wrong structural kind ─────────────────────────── + { + name: "em-arg-where-as-list", + query: `{ User(where: [{id: {_eq: "user-1"}}]) { id } }`, + }, + { + name: "em-arg-where-as-string", + query: `{ User(where: "id") { id } }`, + }, + { + name: "em-arg-order-by-as-enum-literal", + query: `{ User(order_by: asc) { id } }`, + }, + { + name: "em-arg-order-by-as-string", + query: `{ User(order_by: "asc") { id } }`, + }, + { + name: "em-arg-limit-as-object", + query: `{ User(limit: {value: 5}) { id } }`, + }, + { + name: "em-arg-limit-as-list", + query: `{ User(limit: [1]) { id } }`, + }, + { + name: "em-arg-distinct-on-unknown-column", + query: `{ User(distinct_on: notAColumn) { id } }`, + }, + // ── unknown fields and args per nesting level ──────────────────────── + { + name: "em-unknown-field-root-typo", + query: `{ Userz { id } }`, + }, + { + name: "em-unknown-field-object-rel", + query: `{ User(order_by: {id: asc}, limit: 1) { id gravatar { id bogusField } } }`, + }, + { + name: "em-unknown-field-array-rel", + query: `{ User(order_by: {id: asc}, limit: 1) { id tokens { id bogusField } } }`, + }, + { + name: "em-unknown-field-aggregate-wrapper", + role: "admin", + query: `{ Token_aggregate { bogus } }`, + }, + { + name: "em-unknown-field-aggregate-body", + role: "admin", + query: `{ Token_aggregate { aggregate { bogus } } }`, + }, + { + name: "em-unknown-arg-aggregate-count", + role: "admin", + query: `{ Token_aggregate { aggregate { count(bogus: true) } } }`, + }, + { + name: "em-unknown-arg-on-scalar-column", + query: `{ User(order_by: {id: asc}, limit: 1) { id address(bogus: 1) } }`, + }, + // ── duplicate names in document syntax ─────────────────────────────── + { + name: "em-duplicate-argument-name", + query: `{ User(limit: 1, limit: 2) { id } }`, + }, + { + name: "em-duplicate-key-in-input-object", + query: `{ User(where: {id: {_eq: "user-1", _eq: "user-2"}}, order_by: {id: asc}) { id } }`, + }, + { + name: "em-duplicate-variable-definition", + query: `query ($l: Int, $l: Int) { User(order_by: {id: asc}, limit: $l) { id } }`, + variables: { l: 1 }, + }, + // ── malformed string literals ──────────────────────────────────────── + { + name: "em-string-bad-unicode-escape", + query: `{ User_by_pk(id: "\\uZZZZ") { id } }`, + }, + { + name: "em-string-lone-surrogate-escape", + query: `{ User_by_pk(id: "\\uD800") { id } }`, + }, + { + name: "em-string-unknown-escape", + query: `{ User_by_pk(id: "\\q") { id } }`, + }, + { + // The JSON request body itself carries an unpaired surrogate escape. + name: "em-body-lone-surrogate-in-query", + query: `{ User_by_pk(id: "\uD800") { id } }`, + }, + // ── numeric literal overflow ───────────────────────────────────────── + { + name: "em-int-literal-overflow-int32", + query: `{ User(order_by: {id: asc}, limit: 2147483648) { id } }`, + }, + { + name: "em-int-literal-overflow-int64", + query: `{ User(order_by: {id: asc}, limit: 9223372036854775808) { id } }`, + }, + { + name: "em-float-literal-overflow", + query: `{ EntityWithAllNonArrayTypes(where: {float_: {_lt: 1e400}}, order_by: {id: asc}) { id } }`, + }, + // ── variable declaration vs usage mismatches ───────────────────────── + { + name: "em-var-string-decl-used-as-int", + query: `query ($l: String!) { User(order_by: {id: asc}, limit: $l) { id } }`, + variables: { l: "1" }, + }, + { + name: "em-var-wrong-name-used", + query: `query ($lim: Int) { User(order_by: {id: asc}, limit: $limit) { id } }`, + variables: { lim: 1 }, + }, + // ── fragment type conditions ───────────────────────────────────────── + // Hasura does not reject fragments whose type condition can never match: + // it silently drops their selections and answers with the rest. + { + name: "em-fragment-on-scalar-type", + query: `fragment F on String { length } { User(order_by: {id: asc}, limit: 1) { ...F } }`, + }, + { + name: "em-fragment-on-enum-type", + query: `fragment F on order_by { x } { User(order_by: {id: asc}, limit: 1) { ...F } }`, + }, + { + name: "em-inline-fragment-wrong-type", + query: `{ User(order_by: {id: asc}, limit: 1) { id ... on Gravatar { id } } }`, + }, + { + name: "em-inline-fragment-unknown-type", + query: `{ User(order_by: {id: asc}, limit: 1) { id ... on Bogus { id } } }`, + }, + // ── directive location ─────────────────────────────────────────────── + { + name: "em-directive-skip-on-query-operation", + query: `query Q @skip(if: true) { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }`, + }, + // ── by_pk argument shape ───────────────────────────────────────────── + { + name: "em-by-pk-extra-unknown-arg", + query: `{ User_by_pk(id: "user-1", bogus: 1) { id } }`, + }, + { + name: "em-by-pk-id-null-literal", + query: `{ User_by_pk(id: null) { id } }`, + }, + // ── null literals for nullable args (accepted, not errors) ─────────── + { + name: "em-null-literal-limit", + query: `{ SimpleEntity(limit: null, order_by: {id: asc}) { id } }`, + }, + { + name: "em-null-literal-where", + query: `{ SimpleEntity(where: null, order_by: {id: asc}) { id } }`, + }, + // ── degenerate documents ───────────────────────────────────────────── + { + name: "em-empty-selection-braces-field", + query: `{ User(limit: 1) { } }`, + }, + { + name: "em-empty-selection-braces-root", + query: `{ }`, + }, + { + name: "em-comments-only-query", + query: `# just a comment\n# and another one`, + }, + { + name: "em-whitespace-only-query", + query: ` \n\t `, + }, + // ── depth ──────────────────────────────────────────────────────────── + { + name: "em-deep-nesting-40-levels", + query: `{ User_by_pk(id: "user-1") { ${deepGravatarOwner(20)} } }`, + }, + // ── operation kinds over HTTP ──────────────────────────────────────── + { + name: "em-subscription-multiple-root-fields", + query: `subscription { User(limit: 1) { id } Gravatar(limit: 1) { id } }`, + }, + { + name: "em-unknown-operation-type-keyword", + query: `queery { User { id } }`, + }, + // ── request body shape ─────────────────────────────────────────────── + { + name: "em-opname-empty-string", + query: `query Q { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }`, + operationName: "", + }, +]); diff --git a/packages/e2e-tests/src/differential/corpus/index.ts b/packages/e2e-tests/src/differential/corpus/index.ts new file mode 100644 index 0000000000..fb011f9e6a --- /dev/null +++ b/packages/e2e-tests/src/differential/corpus/index.ts @@ -0,0 +1,38 @@ +import basic from "./01-basic.js"; +import where from "./02-where.js"; +import orderPagination from "./03-order-pagination.js"; +import relationships from "./04-relationships.js"; +import scalars from "./05-scalars.js"; +import aggregates from "./06-aggregates.js"; +import internalTables from "./07-internal-tables.js"; +import errors from "./08-errors.js"; +import introspection from "./09-introspection.js"; +import limits from "./10-limits.js"; +import whereMatrix from "./11-where-matrix.js"; +import aggregateMatrix from "./12-aggregate-matrix.js"; +import orderDistinctMatrix from "./13-order-distinct-matrix.js"; +import variablesAndRequest from "./14-variables-and-request.js"; +import scalarSerialization from "./15-scalar-serialization.js"; +import relationshipMatrix from "./16-relationship-matrix.js"; +import errorMatrix from "./17-error-matrix.js"; +import type { CorpusCase } from "../corpus.js"; + +export const allCases: CorpusCase[] = [ + ...basic, + ...where, + ...orderPagination, + ...relationships, + ...scalars, + ...aggregates, + ...internalTables, + ...errors, + ...introspection, + ...limits, + ...whereMatrix, + ...aggregateMatrix, + ...orderDistinctMatrix, + ...variablesAndRequest, + ...scalarSerialization, + ...relationshipMatrix, + ...errorMatrix, +]; diff --git a/packages/e2e-tests/src/differential/diffServe.ts b/packages/e2e-tests/src/differential/diffServe.ts new file mode 100644 index 0000000000..b3951aa6a4 --- /dev/null +++ b/packages/e2e-tests/src/differential/diffServe.ts @@ -0,0 +1,163 @@ +/** + * Iteration helper: runs corpus cases against a running `envio serve` + * instance and diffs them against the recorded Hasura oracle snapshots. + * No Hasura needed. + * + * Usage: pnpm --filter e2e-tests exec tsx src/differential/diffServe.ts \ + * [--phase default|limited] [--filter substr] [--verbose N] + */ + +import { readFile, readdir } from "node:fs/promises"; +import { allCases } from "./corpus/index.js"; +import type { Phase } from "./corpus.js"; +import { serveUrl } from "./env.js"; +import { runCase, normalize, type GraphQLResponse } from "./runner.js"; +import { arg } from "./cliArgs.js"; + +const phase = (arg("--phase") ?? "default") as Phase; +const filter = arg("--filter"); +const verbose = Number(arg("--verbose") ?? 3); +const concurrency = Number(arg("--concurrency") ?? 16); + +const snapshotsDir = new URL( + `../../fixtures/differential/snapshots/${phase}/`, + import.meta.url +); + +interface Snapshot { + status: number; + body: unknown; +} + +function firstDiff(a: unknown, b: unknown, path = "$"): string | undefined { + if (a === b) return undefined; + if (JSON.stringify(a) === JSON.stringify(b)) return undefined; + if ( + typeof a !== typeof b || + a === null || + b === null || + typeof a !== "object" + ) { + return `${path}: oracle=${JSON.stringify(a)?.slice(0, 200)} serve=${JSON.stringify(b)?.slice(0, 200)}`; + } + if (Array.isArray(a) !== Array.isArray(b)) { + return `${path}: array-vs-object mismatch`; + } + if (Array.isArray(a) && Array.isArray(b) && a.length !== b.length) { + return `${path}: array length oracle=${a.length} serve=${b.length}`; + } + const ao = a as Record; + const bo = b as Record; + const keys = new Set([...Object.keys(ao), ...Object.keys(bo)]); + for (const k of keys) { + if (!(k in ao)) return `${path}.${k}: missing in oracle, serve has it`; + if (!(k in bo)) return `${path}.${k}: present in oracle, missing in serve`; + const d = firstDiff(ao[k], bo[k], `${path}.${k}`); + if (d) return d; + } + return `${path}: objects differ in key order only? oracle=${JSON.stringify(ao).slice(0, 100)}`; +} + +async function main() { + const cases = allCases.filter( + (c) => + (c.phases ?? ["default"]).includes(phase) && + (!filter || c.name.includes(filter)) + ); + + let pass = 0; + const failures: { name: string; detail: string }[] = []; + + // A removed/renamed corpus case must not leave its stale snapshot behind + // silently — only meaningful on an unfiltered run, where the full case + // list for the phase is known. + if (!filter) { + const caseNames = new Set(cases.map((c) => c.name)); + const orphans = (await readdir(snapshotsDir)) + .filter((f) => f.endsWith(".json")) + .map((f) => f.slice(0, -".json".length)) + .filter((name) => !caseNames.has(name)) + .sort(); + for (const name of orphans) { + failures.push({ + name, + detail: "orphan snapshot: no corpus case with this name in this phase", + }); + } + } + + const diffOne = async (corpusCase: (typeof cases)[number]) => { + let oracle: Snapshot; + try { + oracle = JSON.parse( + await readFile(new URL(`${corpusCase.name}.json`, snapshotsDir), "utf8") + ) as Snapshot; + } catch { + failures.push({ name: corpusCase.name, detail: "no oracle snapshot" }); + return; + } + let serve: GraphQLResponse; + try { + serve = await runCase(serveUrl, corpusCase); + } catch (err) { + failures.push({ + name: corpusCase.name, + detail: `request failed: ${err instanceof Error ? err.message : err}`, + }); + return; + } + const nOracle = normalize( + { status: oracle.status, body: oracle.body }, + corpusCase.compare + ); + const nServe = normalize(serve, corpusCase.compare); + if (JSON.stringify(nOracle) === JSON.stringify(nServe)) { + pass++; + } else { + const detail = + nOracle.status !== nServe.status + ? `status: oracle=${nOracle.status} serve=${nServe.status} body=${JSON.stringify(nServe.body).slice(0, 200)}` + : (firstDiff(nOracle.body, nServe.body) ?? "unknown diff"); + failures.push({ name: corpusCase.name, detail }); + } + }; + + let next = 0; + await Promise.all( + Array.from({ length: Math.max(1, concurrency) }, async () => { + while (next < cases.length) { + await diffOne(cases[next++]!); + } + }) + ); + failures.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)); + + console.log(`\n${pass}/${cases.length} passed (phase=${phase})`); + if (failures.length > 0) { + console.log(`\nFailures (${failures.length}):`); + const byCategory = new Map(); + for (const f of failures) { + const cat = f.name.split("-")[0] ?? "?"; + byCategory.set(cat, (byCategory.get(cat) ?? 0) + 1); + } + console.log( + "By category:", + [...byCategory.entries()].map(([c, n]) => `${c}:${n}`).join(" ") + ); + for (const f of failures.slice(0, verbose)) { + console.log(`\n--- ${f.name}\n ${f.detail}`); + } + if (failures.length > verbose) { + console.log( + `\n(${failures.length - verbose} more; use --verbose N or --filter)` + ); + for (const f of failures.slice(verbose)) console.log(` ${f.name}`); + } + process.exit(1); + } +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/packages/e2e-tests/src/differential/differential.test.ts b/packages/e2e-tests/src/differential/differential.test.ts new file mode 100644 index 0000000000..93bf5d10b4 --- /dev/null +++ b/packages/e2e-tests/src/differential/differential.test.ts @@ -0,0 +1,56 @@ +/** + * Differential suite: every corpus case is executed against both real Hasura + * and `envio serve`; the responses must match exactly. + * + * Requires Postgres (5433) and Hasura (8080) to be running — the same + * services the other e2e tests use. `envio serve` is spawned by the suite. + */ + +import { describe, it, expect, beforeAll, afterAll } from "vitest"; +import { allCases } from "./corpus/index.js"; +import { phaseConfigs, type Phase } from "./corpus.js"; +import { applyFixture, trackDatabase } from "./hasuraSetup.js"; +import { hasuraUrl, serveUrl } from "./env.js"; +import { runCase, normalize } from "./runner.js"; +import { startServe, stopServe, type ServeProcess } from "./serveProcess.js"; + +const fixtureDir = new URL("../../fixtures/differential/", import.meta.url); + +const phases: Phase[] = ["default", "limited"]; + +describe.sequential("differential", () => { + beforeAll(async () => { + await applyFixture(fixtureDir); + }); + + for (const phase of phases) { + const phaseCases = allCases.filter((c) => + (c.phases ?? ["default"]).includes(phase) + ); + + describe.sequential(`phase: ${phase}`, () => { + let serve: ServeProcess; + + beforeAll(async () => { + await trackDatabase(phaseConfigs[phase]); + serve = await startServe(phaseConfigs[phase]); + }, 120_000); + + afterAll(async () => { + await stopServe(serve); + }); + + for (const corpusCase of phaseCases) { + it(corpusCase.name, async () => { + const [hasura, envio] = await Promise.all([ + runCase(hasuraUrl, corpusCase), + runCase(serveUrl, corpusCase), + ]); + expect(normalize(envio, corpusCase.compare)).toEqual( + normalize(hasura, corpusCase.compare) + ); + }); + } + }); + } +}); diff --git a/packages/e2e-tests/src/differential/env.ts b/packages/e2e-tests/src/differential/env.ts new file mode 100644 index 0000000000..5cc6521849 --- /dev/null +++ b/packages/e2e-tests/src/differential/env.ts @@ -0,0 +1,20 @@ +export const hasuraPort = Number(process.env.HASURA_EXTERNAL_PORT ?? 8080); +export const servePort = Number(process.env.ENVIO_SERVE_PORT ?? 8081); +export const adminSecret = process.env.HASURA_GRAPHQL_ADMIN_SECRET ?? "testing"; + +export const hasuraUrl = `http://localhost:${hasuraPort}`; +export const serveUrl = `http://localhost:${servePort}`; + +export const pgSchema = process.env.ENVIO_PG_SCHEMA ?? "public"; + +export const pg = { + host: process.env.ENVIO_PG_HOST ?? "localhost", + port: Number(process.env.ENVIO_PG_PORT ?? 5433), + user: process.env.ENVIO_PG_USER ?? "postgres", + password: process.env.ENVIO_PG_PASSWORD ?? "testing", + database: process.env.ENVIO_PG_DATABASE ?? "envio-dev", +}; + +export const pgConnectionString = `postgres://${pg.user}:${encodeURIComponent( + pg.password +)}@${pg.host}:${pg.port}/${pg.database}`; diff --git a/packages/e2e-tests/src/differential/fixtureModel.ts b/packages/e2e-tests/src/differential/fixtureModel.ts new file mode 100644 index 0000000000..39fddec80a --- /dev/null +++ b/packages/e2e-tests/src/differential/fixtureModel.ts @@ -0,0 +1,112 @@ +/** + * Static description of the differential fixture (scenarios/test_codegen's + * schema.graphql) in the exact shape Hasura.res derives when tracking: + * which tables are exposed, and the manual object/array relationships. + */ + +export interface ObjectRelationship { + name: string; + /** db column on this table mapping to the remote table's id */ + column: string; + remoteTable: string; + /** GraphQL docstring on the linking field, sent as the relationship's `comment` */ + description?: string; +} + +export interface ArrayRelationship { + name: string; + /** db column on the remote table mapping to this table's id */ + remoteColumn: string; + remoteTable: string; + /** GraphQL docstring on the `@derivedFrom` field, sent as the relationship's `comment` */ + description?: string; +} + +export interface EntityTable { + name: string; + /** GraphQL docstring on the entity type, sent as the table's `comment` */ + description?: string; + /** GraphQL docstrings on scalar fields, keyed by db column name, sent as `column_config[].comment` */ + columnDescriptions?: Record; + objectRelationships?: ObjectRelationship[]; + arrayRelationships?: ArrayRelationship[]; +} + +export const entityTables: EntityTable[] = [ + { + name: "A", + objectRelationships: [{ name: "b", column: "b_id", remoteTable: "B" }], + }, + { + name: "B", + objectRelationships: [{ name: "c", column: "c_id", remoteTable: "C" }], + arrayRelationships: [{ name: "a", remoteColumn: "b_id", remoteTable: "A" }], + }, + { + name: "C", + objectRelationships: [{ name: "a", column: "a_id", remoteTable: "A" }], + arrayRelationships: [{ name: "d", remoteColumn: "c", remoteTable: "D" }], + }, + { name: "CustomSelectionTestPass" }, + { name: "D" }, + { name: "EntityWith63LenghtName______________________________________one" }, + { name: "EntityWith63LenghtName______________________________________two" }, + { name: "EntityWithAllNonArrayTypes" }, + { name: "EntityWithAllTypes" }, + { name: "EntityWithBigDecimal" }, + { name: "EntityWithRestrictedReScriptField" }, + { name: "EntityWithTimestamp" }, + { + name: "Gravatar", + objectRelationships: [ + { name: "owner", column: "owner_id", remoteTable: "User" }, + ], + }, + { + name: "NftCollection", + arrayRelationships: [ + { name: "tokens", remoteColumn: "collection_id", remoteTable: "Token" }, + ], + }, + { name: "PostgresNumericPrecisionEntityTester" }, + { name: "SimpleEntity" }, + { name: "SimulateTestEvent" }, + { + name: "Token", + objectRelationships: [ + { name: "collection", column: "collection_id", remoteTable: "NftCollection" }, + { name: "owner", column: "owner_id", remoteTable: "User" }, + ], + }, + { + name: "User", + description: "A user of the protocol, keyed by their wallet address.", + columnDescriptions: { + address: "The user's wallet address, lowercased.", + }, + objectRelationships: [ + { + name: "gravatar", + column: "gravatar_id", + remoteTable: "Gravatar", + description: "The user's gravatar profile, if they have set one.", + }, + ], + arrayRelationships: [ + { + name: "tokens", + remoteColumn: "owner_id", + remoteTable: "Token", + description: "Tokens currently owned by this user.", + }, + ], + }, +]; + +/** Internal tables tracked by Hasura.trackDatabase alongside user entities. */ +export const internalTables = ["raw_events", "_meta", "chain_metadata"]; + +export const allTrackedTables = [ + ...internalTables, + ...entityTables.map((t) => t.name), +]; diff --git a/packages/e2e-tests/src/differential/hasuraSetup.ts b/packages/e2e-tests/src/differential/hasuraSetup.ts new file mode 100644 index 0000000000..21d520c3e1 --- /dev/null +++ b/packages/e2e-tests/src/differential/hasuraSetup.ts @@ -0,0 +1,155 @@ +/** + * Replicates the exact Hasura metadata configuration that + * packages/envio/src/Hasura.res `trackDatabase` applies at indexer init, + * with the response limit and aggregate-entity set as knobs so test phases + * can vary them without re-running the indexer. + */ + +import { readFile } from "node:fs/promises"; +import { adminSecret, hasuraUrl, pgSchema } from "./env.js"; +import { entityTables, allTrackedTables } from "./fixtureModel.js"; + +async function metadataOp(operation: unknown): Promise { + const res = await fetch(`${hasuraUrl}/v1/metadata`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Hasura-Role": "admin", + "X-Hasura-Admin-Secret": adminSecret, + }, + body: JSON.stringify(operation), + }); + const body = (await res.json()) as { code?: string }; + if (!res.ok) { + const code = body?.code; + if (code === "already-exists" || code === "already-tracked") return body; + throw new Error( + `Hasura metadata op failed (${res.status}): ${JSON.stringify(body)}` + ); + } + return body; +} + +export async function runSql(sql: string): Promise { + const res = await fetch(`${hasuraUrl}/v2/query`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "x-hasura-admin-secret": adminSecret, + }, + body: JSON.stringify({ type: "run_sql", args: { sql } }), + }); + if (!res.ok) { + throw new Error(`run_sql failed (${res.status}): ${await res.text()}`); + } + const body = (await res.json()) as { result?: string[][] }; + return body.result?.slice(1) ?? []; +} + +export async function applyFixture(fixtureDir: URL): Promise { + const schemaSql = await readFile(new URL("schema.sql", fixtureDir), "utf8"); + const seedSql = await readFile(new URL("seed.sql", fixtureDir), "utf8"); + await runSql(schemaSql); + await runSql(seedSql); +} + +export interface TrackOptions { + responseLimit?: number; + aggregateEntities?: string[]; +} + +export async function trackDatabase(options: TrackOptions = {}): Promise { + const { responseLimit, aggregateEntities = [] } = options; + + await metadataOp({ type: "clear_metadata", args: {} }); + await metadataOp({ + type: "reload_metadata", + args: { reload_sources: ["default"] }, + }); + + const entityByName = new Map(entityTables.map((e) => [e.name, e])); + + await metadataOp({ + type: "pg_track_tables", + args: { + allow_warnings: false, + tables: allTrackedTables.map((tableName) => { + const entity = entityByName.get(tableName); + const configuration: Record = { + custom_name: tableName, + }; + if (entity?.description !== undefined) { + configuration.comment = entity.description; + } + const columnDescriptions = entity?.columnDescriptions ?? {}; + if (Object.keys(columnDescriptions).length > 0) { + configuration.column_config = Object.fromEntries( + Object.entries(columnDescriptions).map(([column, comment]) => [ + column, + { comment }, + ]) + ); + } + return { + table: { name: tableName, schema: pgSchema }, + configuration, + }; + }), + }, + }); + + for (const tableName of allTrackedTables) { + const permission: Record = { + columns: "*", + filter: {}, + allow_aggregations: aggregateEntities.includes(tableName), + }; + if (responseLimit !== undefined) permission.limit = responseLimit; + await metadataOp({ + type: "pg_create_select_permission", + args: { + table: { schema: pgSchema, name: tableName }, + role: "public", + source: "default", + permission, + }, + }); + } + + for (const entity of entityTables) { + for (const rel of entity.arrayRelationships ?? []) { + await metadataOp({ + type: "pg_create_array_relationship", + args: { + table: { schema: pgSchema, name: entity.name }, + name: rel.name, + source: "default", + using: { + manual_configuration: { + remote_table: { schema: pgSchema, name: rel.remoteTable }, + column_mapping: { id: rel.remoteColumn }, + }, + }, + ...(rel.description !== undefined && { comment: rel.description }), + }, + }); + } + for (const rel of entity.objectRelationships ?? []) { + await metadataOp({ + type: "pg_create_object_relationship", + args: { + table: { schema: pgSchema, name: entity.name }, + name: rel.name, + source: "default", + using: { + manual_configuration: { + remote_table: { schema: pgSchema, name: rel.remoteTable }, + column_mapping: { [rel.column]: "id" }, + }, + }, + ...(rel.description !== undefined && { comment: rel.description }), + }, + }); + } + } +} diff --git a/packages/e2e-tests/src/differential/record.ts b/packages/e2e-tests/src/differential/record.ts new file mode 100644 index 0000000000..2d5fab667a --- /dev/null +++ b/packages/e2e-tests/src/differential/record.ts @@ -0,0 +1,71 @@ +/** + * Records the corpus responses from real Hasura into snapshots/, providing + * the ground-truth oracle for developing `envio serve` without diffing live. + * + * Usage: pnpm --filter e2e-tests record:differential [--phase default|limited] + */ + +import { mkdir, writeFile, rm } from "node:fs/promises"; +import { allCases } from "./corpus/index.js"; +import { phaseConfigs, type Phase } from "./corpus.js"; +import { applyFixture, trackDatabase } from "./hasuraSetup.js"; +import { hasuraUrl } from "./env.js"; +import { runCase } from "./runner.js"; +import { arg } from "./cliArgs.js"; + +const fixtureDir = new URL("../../fixtures/differential/", import.meta.url); +const snapshotsDir = new URL("snapshots/", fixtureDir); + +const phaseArg = arg("--phase") as Phase | undefined; + +const phases: Phase[] = phaseArg ? [phaseArg] : ["default", "limited"]; + +async function main() { + console.log("Applying fixture schema + seed..."); + await applyFixture(fixtureDir); + + for (const phase of phases) { + console.log(`Tracking Hasura metadata for phase '${phase}'...`); + await trackDatabase(phaseConfigs[phase]); + + const phaseCases = allCases.filter((c) => + (c.phases ?? ["default"]).includes(phase) + ); + console.log(`Recording ${phaseCases.length} cases for phase '${phase}'...`); + + const dir = new URL(`${phase}/`, snapshotsDir); + await rm(dir, { recursive: true, force: true }); + await mkdir(dir, { recursive: true }); + + for (const corpusCase of phaseCases) { + const response = await runCase(hasuraUrl, corpusCase); + const snapshot = { + role: corpusCase.role ?? "public", + request: { + query: corpusCase.query, + ...(corpusCase.variables !== undefined && { + variables: corpusCase.variables, + }), + ...(corpusCase.rawVariables !== undefined && { + rawVariables: corpusCase.rawVariables, + }), + ...(corpusCase.operationName !== undefined && { + operationName: corpusCase.operationName, + }), + }, + status: response.status, + body: response.body, + }; + await writeFile( + new URL(`${corpusCase.name}.json`, dir), + JSON.stringify(snapshot, null, 1) + "\n" + ); + } + } + console.log("Done."); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/packages/e2e-tests/src/differential/runner.ts b/packages/e2e-tests/src/differential/runner.ts new file mode 100644 index 0000000000..1bb1e40547 --- /dev/null +++ b/packages/e2e-tests/src/differential/runner.ts @@ -0,0 +1,74 @@ +import { adminSecret } from "./env.js"; +import type { CorpusCase } from "./corpus.js"; + +export interface GraphQLResponse { + status: number; + body: unknown; +} + +export async function runCase( + endpoint: string, + corpusCase: CorpusCase +): Promise { + const headers: Record = { + "Content-Type": "application/json", + }; + const role = corpusCase.role ?? "public"; + if (role === "admin") { + headers["X-Hasura-Admin-Secret"] = adminSecret; + } else if (role === "admin-wrong") { + headers["X-Hasura-Admin-Secret"] = `${adminSecret}-wrong`; + } + const payload: Record = { query: corpusCase.query }; + if (corpusCase.variables !== undefined) + payload.variables = corpusCase.variables; + if (corpusCase.operationName !== undefined) + payload.operationName = corpusCase.operationName; + + const requestBody = + corpusCase.rawVariables === undefined + ? JSON.stringify(payload) + : `{"query":${JSON.stringify(corpusCase.query)},"variables":${corpusCase.rawVariables}${ + corpusCase.operationName === undefined + ? "" + : `,"operationName":${JSON.stringify(corpusCase.operationName)}` + }}`; + + const res = await fetch(`${endpoint}/v1/graphql`, { + method: "POST", + headers, + body: requestBody, + }); + const text = await res.text(); + let body: unknown; + try { + body = JSON.parse(text); + } catch { + body = { nonJsonBody: text }; + } + return { status: res.status, body }; +} + +/** + * Normalize a response for comparison. For compare mode "rootSet", arrays + * directly under data.* are sorted by their JSON representation so queries + * without a deterministic order_by can still be diffed. + */ +export function normalize( + response: GraphQLResponse, + compare: CorpusCase["compare"] +): GraphQLResponse { + if (compare !== "rootSet") return response; + const body = response.body as { data?: Record }; + if (!body || typeof body !== "object" || !body.data) return response; + const data: Record = {}; + for (const [key, value] of Object.entries(body.data)) { + data[key] = Array.isArray(value) + ? [...value] + .map((item) => [JSON.stringify(item), item] as const) + .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)) + .map(([, item]) => item) + : value; + } + return { status: response.status, body: { ...body, data } }; +} diff --git a/packages/e2e-tests/src/differential/serveLifecycle.test.ts b/packages/e2e-tests/src/differential/serveLifecycle.test.ts new file mode 100644 index 0000000000..60a455614e --- /dev/null +++ b/packages/e2e-tests/src/differential/serveLifecycle.test.ts @@ -0,0 +1,35 @@ +import { expect, it } from "vitest"; +import { phaseConfigs } from "./corpus.js"; +import { servePort } from "./env.js"; +import { spawnServe, waitForServeExit } from "./serveProcess.js"; + +it.runIf(process.platform !== "win32")( + "returns control after Ctrl-C during PostgreSQL startup retry", + async () => { + const starting = spawnServe(phaseConfigs.default, servePort + 1, { + ENVIO_PG_PORT: "1", + ENVIO_SERVE_STARTUP_RETRY_BUDGET_MS: "60000", + }); + try { + // Local workspace runs compile the native addon before startup; CI + // uses a packaged addon. Wait for the actual retry log so SIGINT is + // guaranteed to exercise startup rather than the build wrapper. + const retryDeadline = Date.now() + 60_000; + while ( + !starting.logs.join("").includes("Retrying in") && + Date.now() < retryDeadline + ) { + await new Promise((resolve) => setTimeout(resolve, 50)); + } + expect(starting.logs.join("")).toContain("Retrying in"); + expect(starting.child.kill("SIGINT")).toBe(true); + await expect(waitForServeExit(starting, 5_000)).resolves.toEqual({ + code: 0, + signal: null, + }); + } finally { + if (starting.child.exitCode === null) starting.child.kill("SIGKILL"); + } + }, + 75_000 +); diff --git a/packages/e2e-tests/src/differential/serveProcess.ts b/packages/e2e-tests/src/differential/serveProcess.ts new file mode 100644 index 0000000000..9c840abf25 --- /dev/null +++ b/packages/e2e-tests/src/differential/serveProcess.ts @@ -0,0 +1,123 @@ +import { spawn, type ChildProcess } from "node:child_process"; +import { createRequire } from "node:module"; +import { fileURLToPath } from "node:url"; +import { servePort, serveUrl } from "./env.js"; +import type { TrackOptions } from "./hasuraSetup.js"; + +export interface ServeProcess { + child: ChildProcess; + logs: string[]; +} + +export interface ServeExit { + code: number | null; + signal: NodeJS.Signals | null; +} + +const projectDir = fileURLToPath( + new URL("../../../../scenarios/test_codegen/", import.meta.url) +); +// Resolved through the package dependency so CI (artifact install) and the +// local workspace link both work. +const envioBin = createRequire(import.meta.url).resolve("envio/bin.mjs"); + +export function spawnServe( + options: TrackOptions, + port = servePort, + envOverrides: NodeJS.ProcessEnv = {} +): ServeProcess { + const env: NodeJS.ProcessEnv = { + ...process.env, + ENVIO_SERVE_PORT: String(port), + }; + if (options.responseLimit !== undefined) { + env.ENVIO_HASURA_RESPONSE_LIMIT = String(options.responseLimit); + } else { + delete env.ENVIO_HASURA_RESPONSE_LIMIT; + } + if (options.aggregateEntities && options.aggregateEntities.length > 0) { + env.ENVIO_HASURA_PUBLIC_AGGREGATE = JSON.stringify( + options.aggregateEntities + ); + } else { + delete env.ENVIO_HASURA_PUBLIC_AGGREGATE; + } + Object.assign(env, envOverrides); + + const child = spawn( + process.execPath, + [envioBin, "serve", "--port", String(port)], + { cwd: projectDir, env, stdio: ["ignore", "pipe", "pipe"] } + ); + const logs: string[] = []; + child.stdout?.on("data", (d) => logs.push(d.toString())); + child.stderr?.on("data", (d) => logs.push(d.toString())); + return { child, logs }; +} + +export function waitForServeExit( + serve: ServeProcess, + timeoutMs: number +): Promise { + if (serve.child.exitCode !== null || serve.child.signalCode !== null) { + return Promise.resolve({ + code: serve.child.exitCode, + signal: serve.child.signalCode, + }); + } + return new Promise((resolve, reject) => { + const timer = setTimeout( + () => + reject( + new Error( + `envio serve did not exit within ${timeoutMs}ms:\n${serve.logs.join("")}` + ) + ), + timeoutMs + ); + serve.child.once("exit", (code, signal) => { + clearTimeout(timer); + resolve({ code, signal }); + }); + }); +} + +export async function startServe(options: TrackOptions): Promise { + const serve = spawnServe(options); + const { child, logs } = serve; + + const deadline = Date.now() + 60_000; + while (Date.now() < deadline) { + if (child.exitCode !== null) { + throw new Error( + `envio serve exited with code ${child.exitCode}:\n${logs.join("")}` + ); + } + try { + const res = await fetch(`${serveUrl}/healthz`); + if (res.ok) return serve; + } catch { + // not up yet + } + await new Promise((r) => setTimeout(r, 250)); + } + child.kill("SIGKILL"); + throw new Error(`envio serve did not become healthy:\n${logs.join("")}`); +} + +export async function stopServe(serve: ServeProcess | undefined): Promise { + if (!serve) return; + if (serve.child.exitCode === null) { + serve.child.kill("SIGTERM"); + await new Promise((resolve) => { + const t = setTimeout(() => { + serve.child.kill("SIGKILL"); + resolve(); + }, 5000); + serve.child.once("exit", () => { + clearTimeout(t); + resolve(); + }); + }); + } +} diff --git a/packages/e2e-tests/src/differential/setupBenchDataset.ts b/packages/e2e-tests/src/differential/setupBenchDataset.ts new file mode 100644 index 0000000000..0ded65ac7d --- /dev/null +++ b/packages/e2e-tests/src/differential/setupBenchDataset.ts @@ -0,0 +1,35 @@ +/** + * Applies the differential fixture (schema.sql + seed.sql), tracks it in + * Hasura (default phase), and layers bench-seed.sql on top — the exact + * sequence `bench.ts --record-baseline` expects to already be in place. + * Needs Hasura up (used for both metadata tracking and applying the SQL + * files via its /v2/query endpoint, so no direct pg client dependency is + * needed here — see hasuraSetup.ts). + * + * Usage: pnpm --filter e2e-tests exec tsx src/differential/setupBenchDataset.ts + */ + +import { readFile } from "node:fs/promises"; +import { applyFixture, trackDatabase, runSql } from "./hasuraSetup.js"; +import { phaseConfigs } from "./corpus.js"; + +const fixtureDir = new URL("../../fixtures/differential/", import.meta.url); + +async function main() { + console.log("Applying fixture schema + seed..."); + await applyFixture(fixtureDir); + + console.log("Tracking Hasura metadata (default phase)..."); + await trackDatabase(phaseConfigs.default); + + console.log("Applying bench-seed.sql (large volume)..."); + const sql = await readFile(new URL("bench-seed.sql", fixtureDir), "utf8"); + await runSql(sql); + + console.log("Bench dataset ready."); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/packages/e2e-tests/src/differential/soakLoad.ts b/packages/e2e-tests/src/differential/soakLoad.ts new file mode 100644 index 0000000000..74bb5aaccb --- /dev/null +++ b/packages/e2e-tests/src/differential/soakLoad.ts @@ -0,0 +1,606 @@ +/** + * Concurrent soak/load test for `envio serve`. + * + * Unlike bench.ts (single-connection, per-case latency at concurrency=1), + * this fires a mixed sample of the corpus at N concurrent workers for an + * extended duration and watches for the failure modes that only show up + * under sustained concurrent load: memory leaks (RSS growth), fd leaks, + * and p99 latency degradation over time. It does not check response + * correctness (that's diffServe.ts's job) — only that the server stays up, + * fast, and doesn't 5xx. + * + * `envio serve` must already be running (start it yourself, or pass + * --spawn to have this script start/stop it against scenarios/test_codegen + * — see serveProcess.ts). Resource monitoring (RSS/fd) needs the server's + * PID: with --spawn it's known directly; otherwise pass --pid/--pid-file, + * or this script tries `pgrep -f "bin\.mjs serve"`. If no PID can be + * found, the load test still runs, just without RSS/fd assertions. + * + * Usage: + * # quick local iteration (default 60s, concurrency 32) + * pnpm --filter e2e-tests exec tsx src/differential/soakLoad.ts --spawn + * + * # real acceptance soak + * pnpm --filter e2e-tests exec tsx src/differential/soakLoad.ts \ + * --duration 2h --concurrency 48 --spawn + * + * # against an already-running server + * pnpm --filter e2e-tests exec tsx src/differential/soakLoad.ts \ + * --duration 30m --concurrency 32 --pid 12345 + * + * Flags: + * --duration MS|Ns|Nm|Nh total run time (default 60s) + * --concurrency N in-flight worker count (default 32) + * --url URL target base URL (default env.ts serveUrl) + * --case-pool bench|all corpus subset to sample from (default bench) + * --filter substr restrict pool to case names containing substr + * --spawn spawn+manage envio serve (scenarios/test_codegen) + * --pid N server PID to monitor (skips auto-discovery) + * --pid-file path read the server PID from a file + * --sample-interval MS|Ns RSS/fd sampling period (default 15s) + * --window MS|Ns|Nm latency time-bucket width (default: duration/6, + * clamped to [5s, 5m]) + * --warmup-frac F fraction of run excluded as warmup (default 0.1) + * --rss-growth-pct N fail if RSS grows more than N% (default 20) + * --fd-growth-abs N fail if fd count grows by more than N (default 50) + * --fd-growth-pct N ...or by more than N% of baseline (default 50) + * --p99-drift-multiplier N fail if late p99 > N x early p99 (default 2) + * --report path write the markdown report here (default + * /soak-report.md) + */ + +import { readFileSync, readdirSync } from "node:fs"; +import { execSync } from "node:child_process"; +import { writeFile } from "node:fs/promises"; +import { allCases } from "./corpus/index.js"; +import { serveUrl } from "./env.js"; +import { runCase } from "./runner.js"; +import { startServe, stopServe, type ServeProcess } from "./serveProcess.js"; +import { phaseConfigs } from "./corpus.js"; +import type { CorpusCase } from "./corpus.js"; + +// --------------------------------------------------------------------------- +// CLI args + +const argv = process.argv.slice(2); +const flag = (name: string) => argv.includes(name); +const arg = (name: string): string | undefined => { + const i = argv.indexOf(name); + return i >= 0 ? argv[i + 1] : undefined; +}; + +/** Accepts a plain number (ms) or Ns / Nm / Nh (seconds/minutes/hours). */ +function parseDuration(input: string): number { + const m = /^(\d+(?:\.\d+)?)(ms|s|m|h)?$/.exec(input.trim()); + if (!m) throw new Error(`Invalid duration: ${input}`); + const n = Number(m[1]); + switch (m[2]) { + case "h": + return n * 3_600_000; + case "m": + return n * 60_000; + case "s": + return n * 1_000; + case "ms": + case undefined: + return n; + default: + throw new Error(`Invalid duration unit: ${input}`); + } +} + +const durationMs = parseDuration(arg("--duration") ?? "60s"); +const concurrency = Math.max(1, Number(arg("--concurrency") ?? 32)); +const targetUrl = arg("--url") ?? serveUrl; +const casePool = (arg("--case-pool") ?? "bench") as "bench" | "all"; +const caseFilter = arg("--filter"); +const shouldSpawn = flag("--spawn"); +const explicitPid = arg("--pid") ? Number(arg("--pid")) : undefined; +const pidFile = arg("--pid-file"); +const sampleIntervalMs = parseDuration(arg("--sample-interval") ?? "15s"); +const windowMs = arg("--window") + ? parseDuration(arg("--window")!) + : Math.min(5 * 60_000, Math.max(5_000, Math.floor(durationMs / 6))); +const warmupFrac = Number(arg("--warmup-frac") ?? 0.1); +const rssGrowthPctThreshold = Number(arg("--rss-growth-pct") ?? 20); +const fdGrowthAbsThreshold = Number(arg("--fd-growth-abs") ?? 50); +const fdGrowthPctThreshold = Number(arg("--fd-growth-pct") ?? 50); +const p99DriftMultiplier = Number(arg("--p99-drift-multiplier") ?? 2); +const reportPath = arg("--report"); + +// --------------------------------------------------------------------------- +// Case pool + +function selectPool(): CorpusCase[] { + const pool = allCases.filter( + (c) => + (c.phases ?? ["default"]).includes("default") && + (casePool === "all" ? c.compare !== "rootSet" : c.bench === true) && + (!caseFilter || c.name.includes(caseFilter)) + ); + if (pool.length === 0) { + throw new Error( + `No corpus cases matched --case-pool ${casePool}${caseFilter ? ` --filter ${caseFilter}` : ""}` + ); + } + return pool; +} + +// --------------------------------------------------------------------------- +// Reservoir-sampled latency stats (bounded memory over a multi-hour run) + +class Reservoir { + private samples: number[] = []; + private seen = 0; + constructor(private readonly cap: number) {} + + add(value: number) { + this.seen++; + if (this.samples.length < this.cap) { + this.samples.push(value); + } else { + const j = Math.floor(Math.random() * this.seen); + if (j < this.cap) this.samples[j] = value; + } + } + + get count(): number { + return this.seen; + } + + percentile(q: number): number | undefined { + if (this.samples.length === 0) return undefined; + const sorted = [...this.samples].sort((a, b) => a - b); + return sorted[Math.min(sorted.length - 1, Math.floor(q * sorted.length))]; + } +} + +interface WindowStats { + index: number; + startMs: number; + reservoir: Reservoir; + count: number; + errorCount: number; +} + +// --------------------------------------------------------------------------- +// Resource (RSS + fd) sampling via /proc — no shelling out, portable to any +// Linux box without extra deps. + +interface ResourceSample { + tMs: number; + rssKb: number; + fdCount: number; +} + +class ResourceMonitor { + samples: ResourceSample[] = []; + private timer?: NodeJS.Timeout; + private missCount = 0; + onProcessGone?: () => void; + + constructor( + private readonly pid: number, + private readonly startedAt: number + ) {} + + private snapshot(): ResourceSample | undefined { + try { + const status = readFileSync(`/proc/${this.pid}/status`, "utf8"); + const m = /VmRSS:\s+(\d+) kB/.exec(status); + const rssKb = m ? Number(m[1]) : 0; + const fdCount = readdirSync(`/proc/${this.pid}/fd`).length; + this.missCount = 0; + return { tMs: Date.now() - this.startedAt, rssKb, fdCount }; + } catch { + return undefined; + } + } + + start() { + const first = this.snapshot(); + if (first) this.samples.push(first); + this.timer = setInterval(() => { + const s = this.snapshot(); + if (s) { + this.samples.push(s); + } else { + this.missCount++; + // A couple of misses can be a raced read; several in a row means + // the server process has exited mid-soak — that's a hard failure, + // not a monitoring hiccup. + if (this.missCount >= 3) this.onProcessGone?.(); + } + }, sampleIntervalMs); + this.timer.unref(); + } + + stop() { + if (this.timer) clearInterval(this.timer); + } +} + +function pidByCommand(pattern: string): number | undefined { + try { + const out = execSync(`pgrep -f ${JSON.stringify(pattern)}`, { + encoding: "utf8", + }) + .trim() + .split("\n") + .filter(Boolean) + .map(Number); + return out[0]; + } catch { + return undefined; + } +} + +// --------------------------------------------------------------------------- + +interface RunResult { + pass: boolean; + reasons: string[]; +} + +async function main() { + const pool = selectPool(); + console.log( + `Soak load: ${pool.length} corpus cases (pool=${casePool}${caseFilter ? `, filter=${caseFilter}` : ""}), ` + + `concurrency=${concurrency}, duration=${(durationMs / 1000).toFixed(0)}s, window=${(windowMs / 1000).toFixed(0)}s, target=${targetUrl}` + ); + + let serve: ServeProcess | undefined; + let pid: number | undefined = explicitPid; + + if (shouldSpawn) { + console.log("Spawning envio serve (scenarios/test_codegen)..."); + serve = await startServe(phaseConfigs.default); + pid = serve.child.pid; + console.log(`envio serve up, pid=${pid}`); + } else { + // Confirm the target is actually reachable before burning the whole + // run against a dead server. + try { + const res = await fetch(`${targetUrl}/healthz`); + if (!res.ok) throw new Error(`status ${res.status}`); + } catch (err) { + console.error( + `${targetUrl}/healthz not reachable (${err instanceof Error ? err.message : err}). ` + + "Start envio serve first, or pass --spawn." + ); + process.exit(1); + } + if (pid === undefined && pidFile) { + pid = Number(readFileSync(pidFile, "utf8").trim()); + } + if (pid === undefined) { + pid = pidByCommand("bin\\.mjs serve"); + } + } + + if (pid === undefined) { + console.warn( + "WARNING: could not determine envio serve's PID (no --pid/--pid-file, " + + "no --spawn, and pgrep found no match). Running the load test WITHOUT " + + "RSS/fd leak assertions — only latency and status-code checks apply." + ); + } else { + console.log(`Monitoring resource usage for pid ${pid}`); + } + + try { + const result = await runSoak(pool, pid); + if (!result.pass) { + console.error("\nSOAK FAILED:"); + for (const r of result.reasons) console.error(` - ${r}`); + process.exitCode = 1; + } else { + console.log("\nSOAK PASSED"); + } + } finally { + await stopServe(serve); + } +} + +async function runSoak( + pool: CorpusCase[], + pid: number | undefined +): Promise { + const startedAt = Date.now(); + const endAt = startedAt + durationMs; + + const globalReservoir = new Reservoir(20_000); + const windows: WindowStats[] = []; + const windowFor = (tMs: number): WindowStats => { + const idx = Math.floor(tMs / windowMs); + let w = windows[idx]; + if (!w) { + w = { index: idx, startMs: idx * windowMs, reservoir: new Reservoir(3_000), count: 0, errorCount: 0 }; + windows[idx] = w; + } + return w; + }; + + const statusCounts = new Map(); + let total = 0; + let count5xx = 0; + let networkErrors = 0; + + let monitor: ResourceMonitor | undefined; + let processDied = false; + if (pid !== undefined) { + monitor = new ResourceMonitor(pid, startedAt); + monitor.onProcessGone = () => { + processDied = true; + }; + monitor.start(); + } + + let stopRequested = false; + + const worker = async () => { + while (!stopRequested && Date.now() < endAt && !processDied) { + const c = pool[Math.floor(Math.random() * pool.length)]!; + // Bucket by when the request STARTED, not when it completed — a slow + // request issued near a window boundary should count against the + // window that issued it, not skew whichever (possibly tiny, partial) + // window it happens to land in once it finally finishes. + const w = windowFor(Date.now() - startedAt); + const t0 = performance.now(); + let status: number; + try { + const res = await runCase(targetUrl, c); + status = res.status; + } catch { + status = 0; // transport-level failure (refused/reset/timeout) + } + const latencyMs = performance.now() - t0; + + total++; + statusCounts.set(status, (statusCounts.get(status) ?? 0) + 1); + if (status === 0) networkErrors++; + else if (status >= 500) count5xx++; + + globalReservoir.add(latencyMs); + w.count++; + w.reservoir.add(latencyMs); + if (status === 0 || status >= 500) w.errorCount++; + + if (status === 0) { + // Back off briefly so a dead server doesn't turn into a hot spin + // loop that floods logs and pegs a CPU for the rest of the run. + await new Promise((r) => setTimeout(r, 50)); + } + } + }; + + const heartbeatEveryMs = Math.min(30_000, windowMs); + const heartbeat = setInterval(() => { + const elapsedS = ((Date.now() - startedAt) / 1000).toFixed(0); + const last = monitor?.samples.at(-1); + const rss = last ? `${(last.rssKb / 1024).toFixed(0)}MB` : "n/a"; + const fd = last ? String(last.fdCount) : "n/a"; + console.log( + `[${elapsedS}s] requests=${total} 5xx=${count5xx} netErr=${networkErrors} rss=${rss} fd=${fd}` + ); + }, heartbeatEveryMs); + heartbeat.unref(); + + await Promise.all(Array.from({ length: concurrency }, () => worker())); + stopRequested = true; + clearInterval(heartbeat); + monitor?.stop(); + + return buildReport({ + startedAt, + actualDurationMs: Date.now() - startedAt, + total, + count5xx, + networkErrors, + statusCounts, + globalReservoir, + windows: windows.filter((w): w is WindowStats => w !== undefined), + resourceSamples: monitor?.samples ?? [], + processDied, + pid, + }); +} + +interface ReportInput { + startedAt: number; + actualDurationMs: number; + total: number; + count5xx: number; + networkErrors: number; + statusCounts: Map; + globalReservoir: Reservoir; + windows: WindowStats[]; + resourceSamples: ResourceSample[]; + processDied: boolean; + pid: number | undefined; +} + +function avg(xs: number[]): number | undefined { + return xs.length === 0 ? undefined : xs.reduce((a, b) => a + b, 0) / xs.length; +} + +async function buildReport(input: ReportInput): Promise { + const reasons: string[] = []; + const { + actualDurationMs, + total, + count5xx, + networkErrors, + statusCounts, + globalReservoir, + windows, + resourceSamples, + processDied, + pid, + } = input; + + if (processDied) { + reasons.push( + `envio serve (pid ${pid}) stopped responding on /proc partway through the run — the process likely crashed or exited.` + ); + } + if (count5xx > 0) { + reasons.push(`${count5xx} HTTP 5xx response(s) out of ${total} requests.`); + } + if (networkErrors > 0) { + reasons.push( + `${networkErrors} transport-level failure(s) (connection refused/reset/timeout) out of ${total} requests.` + ); + } + + // Latency: compare an early "stabilized" window against the last window. + // A trailing window can be a sliver (the run stops issuing new requests + // at the deadline, but a handful of slow in-flight ones still land in + // whatever window is current) — comparing against a handful of samples + // is noise, not a trend, so only windows with a representative sample + // count are eligible for the comparison itself (the full per-window + // table below still reports every window, sliver or not). + const warmupEndMs = actualDurationMs * warmupFrac; + const stabilized = windows.filter((w) => w.startMs >= warmupEndMs); + const sortedCounts = [...stabilized.map((w) => w.count)].sort((a, b) => a - b); + const medianCount = sortedCounts[Math.floor(sortedCounts.length / 2)] ?? 0; + const minReliableCount = Math.max(5, medianCount * 0.4); + const reliable = stabilized.filter((w) => w.count >= minReliableCount); + const earlyWindow = reliable[0]; + const lateWindow = reliable.at(-1); + const earlyP99 = earlyWindow?.reservoir.percentile(0.99); + const lateP99 = lateWindow?.reservoir.percentile(0.99); + let p99DriftRatio: number | undefined; + if (earlyP99 !== undefined && lateP99 !== undefined && earlyP99 > 0) { + p99DriftRatio = lateP99 / earlyP99; + if ( + earlyWindow !== lateWindow && + p99DriftRatio > p99DriftMultiplier && + lateP99 - earlyP99 > 5 // ignore drift entirely within sub-5ms noise + ) { + reasons.push( + `p99 latency drifted from ${earlyP99.toFixed(1)}ms (window ${earlyWindow!.index}) to ${lateP99.toFixed(1)}ms ` + + `(window ${lateWindow!.index}) — x${p99DriftRatio.toFixed(2)}, threshold x${p99DriftMultiplier}.` + ); + } + } + + // RSS / fd: baseline = average over the stabilized window right after + // warmup; final = average over the last ~10% of the run. + const postWarmup = resourceSamples.filter((s) => s.tMs >= warmupEndMs); + const baselineWindowEnd = warmupEndMs + actualDurationMs * 0.2; + const baselineSamples = postWarmup.filter((s) => s.tMs <= baselineWindowEnd); + const finalWindowStart = actualDurationMs * 0.9; + const finalSamples = resourceSamples.filter((s) => s.tMs >= finalWindowStart); + + const rssBaselineKb = avg((baselineSamples.length ? baselineSamples : postWarmup).map((s) => s.rssKb)); + const rssFinalKb = avg((finalSamples.length ? finalSamples : postWarmup).map((s) => s.rssKb)); + let rssGrowthPct: number | undefined; + if (rssBaselineKb !== undefined && rssFinalKb !== undefined && rssBaselineKb > 0) { + rssGrowthPct = ((rssFinalKb - rssBaselineKb) / rssBaselineKb) * 100; + if (rssGrowthPct > rssGrowthPctThreshold) { + reasons.push( + `RSS grew ${rssGrowthPct.toFixed(1)}% from stabilized baseline (${(rssBaselineKb / 1024).toFixed(0)}MB -> ${(rssFinalKb / 1024).toFixed(0)}MB), ` + + `threshold ${rssGrowthPctThreshold}%.` + ); + } + } + + const fdBaseline = avg((baselineSamples.length ? baselineSamples : postWarmup).map((s) => s.fdCount)); + const fdFinal = avg((finalSamples.length ? finalSamples : postWarmup).map((s) => s.fdCount)); + let fdGrowthAbs: number | undefined; + if (fdBaseline !== undefined && fdFinal !== undefined) { + fdGrowthAbs = fdFinal - fdBaseline; + const fdThreshold = Math.max(fdGrowthAbsThreshold, fdBaseline * (fdGrowthPctThreshold / 100)); + if (fdGrowthAbs > fdThreshold) { + reasons.push( + `Open fd count grew by ${fdGrowthAbs.toFixed(0)} from stabilized baseline (${fdBaseline.toFixed(0)} -> ${fdFinal.toFixed(0)}), ` + + `threshold ${fdThreshold.toFixed(0)} (max of ${fdGrowthAbsThreshold} abs / ${fdGrowthPctThreshold}% of baseline).` + ); + } + } + + const overallP50 = globalReservoir.percentile(0.5); + const overallP99 = globalReservoir.percentile(0.99); + const errorRate = total > 0 ? ((count5xx + networkErrors) / total) * 100 : 0; + const rps = total / (actualDurationMs / 1000); + + const lines: string[] = []; + lines.push(`# Soak load report`); + lines.push(""); + lines.push( + `Duration ${(actualDurationMs / 1000).toFixed(0)}s, concurrency ${concurrency}, target ${targetUrl}, ${total} requests (${rps.toFixed(1)} req/s).` + ); + lines.push(""); + lines.push(`## Status codes`); + lines.push(""); + for (const [status, n] of [...statusCounts.entries()].sort((a, b) => a[0] - b[0])) { + lines.push(`- ${status === 0 ? "transport error" : status}: ${n} (${((n / total) * 100).toFixed(2)}%)`); + } + lines.push(""); + lines.push(`Error rate (5xx + transport): **${errorRate.toFixed(3)}%**`); + lines.push(""); + lines.push(`## Latency`); + lines.push(""); + lines.push(`Overall p50 ${overallP50?.toFixed(1) ?? "n/a"}ms, p99 ${overallP99?.toFixed(1) ?? "n/a"}ms (n=${globalReservoir.count}).`); + lines.push(""); + lines.push(`| window | start (s) | requests | errors | p50 (ms) | p99 (ms) |`); + lines.push(`|---|---|---|---|---|---|`); + for (const w of windows) { + lines.push( + `| ${w.index} | ${(w.startMs / 1000).toFixed(0)} | ${w.count} | ${w.errorCount} | ${w.reservoir.percentile(0.5)?.toFixed(1) ?? "n/a"} | ${w.reservoir.percentile(0.99)?.toFixed(1) ?? "n/a"} |` + ); + } + lines.push(""); + if (earlyP99 !== undefined && lateP99 !== undefined) { + lines.push( + `p99 drift: window ${earlyWindow!.index} (${earlyP99.toFixed(1)}ms) -> window ${lateWindow!.index} (${lateP99.toFixed(1)}ms), x${p99DriftRatio?.toFixed(2)} (threshold x${p99DriftMultiplier}).` + ); + } else { + lines.push(`p99 drift: not enough stabilized windows to compare (run longer than the warmup fraction, or lower --window).`); + } + lines.push(""); + lines.push(`## Resource usage (pid ${pid ?? "n/a"})`); + lines.push(""); + if (resourceSamples.length > 0) { + const first = resourceSamples[0]!; + const last = resourceSamples.at(-1)!; + const peakRssKb = Math.max(...resourceSamples.map((s) => s.rssKb)); + lines.push( + `RSS: start ${(first.rssKb / 1024).toFixed(0)}MB, stabilized baseline ${rssBaselineKb ? (rssBaselineKb / 1024).toFixed(0) : "n/a"}MB, ` + + `final ${rssFinalKb ? (rssFinalKb / 1024).toFixed(0) : "n/a"}MB, peak ${(peakRssKb / 1024).toFixed(0)}MB, growth ${rssGrowthPct?.toFixed(1) ?? "n/a"}% (threshold ${rssGrowthPctThreshold}%).` + ); + lines.push( + `fd count: start ${first.fdCount}, stabilized baseline ${fdBaseline?.toFixed(0) ?? "n/a"}, final ${last.fdCount}, growth ${fdGrowthAbs?.toFixed(0) ?? "n/a"}.` + ); + } else if (pid === undefined) { + lines.push(`No PID available — RSS/fd were not monitored for this run.`); + } else { + lines.push(`No resource samples collected for pid ${pid} — it may have exited before the first sample.`); + } + lines.push(""); + lines.push(`## Result`); + lines.push(""); + if (reasons.length === 0) { + lines.push(`PASS`); + } else { + lines.push(`FAIL:`); + for (const r of reasons) lines.push(`- ${r}`); + } + + const report = lines.join("\n") + "\n"; + console.log("\n" + report); + + const out = reportPath + ? new URL(reportPath, `file://${process.cwd()}/`) + : new URL("../../soak-report.md", import.meta.url); + await writeFile(out, report); + console.log(`Report written to ${out.pathname}`); + + return { pass: reasons.length === 0, reasons }; +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/packages/e2e-tests/src/differential/subscriptions.test.ts b/packages/e2e-tests/src/differential/subscriptions.test.ts new file mode 100644 index 0000000000..cdb78da47d --- /dev/null +++ b/packages/e2e-tests/src/differential/subscriptions.test.ts @@ -0,0 +1,503 @@ +/** + * Differential WebSocket subscription suite: identical scenarios executed + * against real Hasura and `envio serve`, comparing payloads frame-by-frame + * (timing-insensitive: only order and content of data payloads matter). + * + * Covers both subprotocols Hasura serves on /v1/graphql. + */ + +import { describe, it, expect, beforeAll, afterAll } from "vitest"; +import { applyFixture, trackDatabase, runSql } from "./hasuraSetup.js"; +import { phaseConfigs } from "./corpus.js"; +import { adminSecret, hasuraPort, servePort } from "./env.js"; +import { connect, subscribe, type WsProtocol } from "./wsClient.js"; +import { + spawnServe, + startServe, + stopServe, + waitForServeExit, + type ServeProcess, +} from "./serveProcess.js"; + +const fixtureDir = new URL("../../fixtures/differential/", import.meta.url); + +const endpoints = { + hasura: `ws://localhost:${hasuraPort}/v1/graphql`, + envio: `ws://localhost:${servePort}/v1/graphql`, +}; + +const protocols: WsProtocol[] = ["graphql-transport-ws", "graphql-ws"]; + +interface ScenarioResult { + payloads: unknown[]; + errorPayload?: unknown; +} + +describe.sequential("differential subscriptions", () => { + let serve: ServeProcess; + + beforeAll(async () => { + await applyFixture(fixtureDir); + await trackDatabase(phaseConfigs.default); + serve = await startServe(phaseConfigs.default); + }, 180_000); + + afterAll(async () => { + await stopServe(serve); + }); + + for (const protocol of protocols) { + describe.sequential(protocol, () => { + it("live query: initial payload, update on insert, stop", async () => { + const query = `subscription { SimpleEntity(order_by: {id: asc}, where: {id: {_like: "sub-tmp%"}}) { id value } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + const payloads: unknown[] = []; + try { + const sub = subscribe(session, protocol, { query }); + payloads.push(await sub.nextData()); + await runSql( + `INSERT INTO public."SimpleEntity" (id, value) VALUES ('sub-tmp-1', 'live');` + ); + payloads.push(await sub.nextData()); + session.assertNoUnconsumedData(); + sub.stop(); + } finally { + await session.close(); + await runSql(`DELETE FROM public."SimpleEntity" WHERE id LIKE 'sub-tmp%';`); + } + return { payloads }; + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.payloads).toEqual(hasura.payloads); + }, 90_000); + + it("by_pk subscription with variables", async () => { + const query = `subscription ($id: String!) { User_by_pk(id: $id) { id updatesCountOnUserForTesting } }`; + const variables = { id: "user-1" }; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + const payloads: unknown[] = []; + try { + const sub = subscribe(session, protocol, { query, variables }); + payloads.push(await sub.nextData()); + await runSql( + `UPDATE public."User" SET "updatesCountOnUserForTesting" = 777 WHERE id = 'user-1';` + ); + payloads.push(await sub.nextData()); + session.assertNoUnconsumedData(); + sub.stop(); + } finally { + await session.close(); + await runSql( + `UPDATE public."User" SET "updatesCountOnUserForTesting" = 0 WHERE id = 'user-1';` + ); + } + return { payloads }; + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.payloads).toEqual(hasura.payloads); + }, 90_000); + + it("query over websocket completes after one payload", async () => { + const query = `{ SimpleEntity(order_by: {id: asc}, limit: 2) { id value } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + try { + const sub = subscribe(session, protocol, { query }); + const first = await sub.nextData(); + await sub.waitComplete(); + session.assertNoUnconsumedData(); + return { payloads: [first] }; + } finally { + await session.close(); + } + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.payloads).toEqual(hasura.payloads); + }, 60_000); + + it("validation error surfaces as protocol error frame", async () => { + const query = `subscription { NotATable { id } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + try { + const sub = subscribe(session, protocol, { query }); + const errorPayload = await sub.nextError(); + return { payloads: [], errorPayload }; + } finally { + await session.close(); + } + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.errorPayload).toEqual(hasura.errorPayload); + }, 60_000); + + it("public role subscription is limited to public schema", async () => { + const query = `subscription { User_aggregate { aggregate { count } } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, {}); + try { + const sub = subscribe(session, protocol, { query }); + const errorPayload = await sub.nextError(); + return { payloads: [], errorPayload }; + } finally { + await session.close(); + } + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.errorPayload).toEqual(hasura.errorPayload); + }, 60_000); + + it("streaming subscription advances the cursor", async () => { + const query = `subscription { SimulateTestEvent_stream(batch_size: 2, cursor: {initial_value: {blockNumber: 0}, ordering: ASC}) { id blockNumber logIndex } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + const payloads: unknown[] = []; + try { + const sub = subscribe(session, protocol, { query }); + payloads.push(await sub.nextData()); + payloads.push(await sub.nextData()); + payloads.push(await sub.nextData()); + session.assertNoUnconsumedData(); + sub.stop(); + } finally { + await session.close(); + } + return { payloads }; + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.payloads).toEqual(hasura.payloads); + }, 90_000); + + it("streaming subscription preserves an explicit NULL cursor boundary", async () => { + const query = `subscription { User_stream(batch_size: 2, cursor: {initial_value: {gravatar_id: null}, ordering: DESC}) { id gravatar_id } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + try { + const sub = subscribe(session, protocol, { query }); + // Hasura keeps explicit NULL as the cursor value. The resulting + // strict SQL comparison matches no rows, so no batch is emitted. + // Waiting across two poll intervals distinguishes this from the + // old behavior, which dropped NULL and streamed unbounded rows. + await new Promise((resolve) => setTimeout(resolve, 2_500)); + session.assertNoUnconsumedData(); + sub.stop(); + } finally { + await session.close(); + } + return { payloads: [] }; + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.payloads).toEqual(hasura.payloads); + }, 90_000); + + it("query variables preserve numbers outside f64 range", async () => { + const query = `query ($n: numeric!, $j: jsonb!) { numeric: Token(where: {tokenId: {_eq: $n}}, order_by: {id: asc}) { id } json: EntityWithAllTypes(where: {json: {_contains: $j}}, order_by: {id: asc}) { id } }`; + const rawVariables = `{"n":1e400,"j":{"nested":-9e999}}`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + const id = "overflow-vars"; + const startType = protocol === "graphql-transport-ws" ? "subscribe" : "start"; + const dataType = protocol === "graphql-transport-ws" ? "next" : "data"; + try { + session.sendRaw( + `{"type":${JSON.stringify(startType)},"id":${JSON.stringify(id)},"payload":{"query":${JSON.stringify(query)},"variables":${rawVariables}}}` + ); + const frame = await session.next( + (candidate) => + candidate.id === id && + (candidate.type === dataType || candidate.type === "error") + ); + if (frame.type === "error") { + return { payloads: [], errorPayload: frame.payload }; + } + await session.next( + (candidate) => candidate.id === id && candidate.type === "complete" + ); + return { payloads: [frame.payload] }; + } finally { + await session.close(); + } + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio).toEqual(hasura); + }, 60_000); + + it("streaming subscription loses rows tied with the cursor boundary", async () => { + // Hasura's single-column stream cursor has no tie-breaking: with + // batch_size 1, sim-1 and sim-2 both have blockNumber 100. Batch 1 + // returns only sim-1 (arbitrary pick among ties); the cursor then + // advances to blockNumber=100 and the next query's strict `> 100` + // bound permanently skips sim-2. This is real, observed Hasura + // v2.43.0 behavior (verified live) — not an idealized "WITH TIES" + // protection — and envio serve must reproduce it exactly rather + // than "fix" it. + const query = `subscription { SimulateTestEvent_stream(batch_size: 1, cursor: {initial_value: {blockNumber: 0}, ordering: ASC}) { id blockNumber } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + const payloads: unknown[] = []; + try { + const sub = subscribe(session, protocol, { query }); + payloads.push(await sub.nextData()); + payloads.push(await sub.nextData()); + payloads.push(await sub.nextData()); + session.assertNoUnconsumedData(); + sub.stop(); + } finally { + await session.close(); + } + return { payloads }; + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.payloads).toEqual(hasura.payloads); + }, 90_000); + + it.each([ + ["cursor: []", "[]"], + ["cursor: [null]", "[null]"], + ])( + "streaming subscription rejects an empty cursor (%s)", + async (_label, cursorLiteral) => { + const query = `subscription { SimulateTestEvent_stream(batch_size: 2, cursor: ${cursorLiteral}) { id blockNumber } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + try { + const sub = subscribe(session, protocol, { query }); + const errorPayload = await sub.nextError(); + return { payloads: [], errorPayload }; + } finally { + await session.close(); + } + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.errorPayload).toEqual(hasura.errorPayload); + }, + 60_000 + ); + + it("streaming subscription rejects a null cursor", async () => { + const query = `subscription { SimulateTestEvent_stream(batch_size: 2, cursor: null) { id blockNumber } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + try { + const sub = subscribe(session, protocol, { query }); + const errorPayload = await sub.nextError(); + return { payloads: [], errorPayload }; + } finally { + await session.close(); + } + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.errorPayload).toEqual(hasura.errorPayload); + }, 60_000); + + // Functional GraphQL behavior is diffed against Hasura above. For + // connection-level misuse, graphql-transport-ws itself is the oracle: + // it mandates 4409/4401/4429, while Hasura v2.43 closes normally or + // accepts a repeated init. The legacy protocol has no equivalent + // mandated behavior, so these run only for the modern protocol. + if (protocol === "graphql-transport-ws") { + it("duplicate subscription id on one socket closes with 4409", async () => { + const query = `subscription { SimpleEntity(order_by: {id: asc}, limit: 1) { id } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + try { + const sub = subscribe(session, protocol, { query }, "dup-id"); + await sub.nextData(); + subscribe(session, protocol, { query }, "dup-id"); + return (await session.waitClose()).code; + } finally { + await session.close(); + } + }; + + const envio = await run(endpoints.envio); + expect(envio).toBe(4409); + }, 60_000); + + it("subscribe before connection_init closes with 4401", async () => { + const query = `subscription { SimpleEntity(limit: 1) { id } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { skipInit: true }); + try { + session.send({ type: "subscribe", id: "1", payload: { query } }); + return (await session.waitClose()).code; + } finally { + await session.close(); + } + }; + + const envio = await run(endpoints.envio); + expect(envio).toBe(4401); + }, 60_000); + + it("second connection_init closes with 4429", async () => { + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + try { + session.send({ type: "connection_init", payload: {} }); + return (await session.waitClose()).code; + } finally { + await session.close(); + } + }; + + const envio = await run(endpoints.envio); + expect(envio).toBe(4429); + }, 60_000); + } + + it("concurrent subscriptions on one socket receive independent updates", async () => { + const queryFor = (prefix: string) => + `subscription { SimpleEntity(order_by: {id: asc}, where: {id: {_like: "${prefix}%"}}) { id value } }`; + + const run = async (url: string): Promise => { + const session = await connect(url, protocol, { adminSecret }); + const payloads: unknown[] = []; + try { + const subA = subscribe(session, protocol, { query: queryFor("multi-a") }); + const subB = subscribe(session, protocol, { query: queryFor("multi-b") }); + payloads.push(await subA.nextData()); + payloads.push(await subB.nextData()); + await runSql( + `INSERT INTO public."SimpleEntity" (id, value) VALUES ('multi-a-1', 'a');` + ); + payloads.push(await subA.nextData()); + await runSql( + `INSERT INTO public."SimpleEntity" (id, value) VALUES ('multi-b-1', 'b');` + ); + payloads.push(await subB.nextData()); + // A spurious extra push on either subscription (e.g. sub B + // reacting to sub A's row) is exactly what this scenario must + // catch. + session.assertNoUnconsumedData(); + subA.stop(); + subB.stop(); + } finally { + await session.close(); + await runSql(`DELETE FROM public."SimpleEntity" WHERE id LIKE 'multi-%';`); + } + return { payloads }; + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.payloads).toEqual(hasura.payloads); + }, 90_000); + + it("rapid connect/disconnect churn leaves the server healthy", async () => { + const query = `subscription { SimpleEntity(order_by: {id: asc}, limit: 1) { id value } }`; + + const run = async (url: string): Promise => { + for (let i = 0; i < 5; i++) { + const session = await connect(url, protocol, { adminSecret }); + subscribe(session, protocol, { query }); + await session.close(); + } + const session = await connect(url, protocol, { adminSecret }); + try { + const sub = subscribe(session, protocol, { query }); + const payload = await sub.nextData(); + session.assertNoUnconsumedData(); + sub.stop(); + return { payloads: [payload] }; + } finally { + await session.close(); + } + }; + + const hasura = await run(endpoints.hasura); + const envio = await run(endpoints.envio); + expect(envio.payloads).toEqual(hasura.payloads); + }, 90_000); + }); + } + + it("reports actionable PostgreSQL startup errors", async () => { + const failed = spawnServe(phaseConfigs.default, servePort + 1, { + ENVIO_PG_PORT: "1", + ENVIO_SERVE_STARTUP_RETRY_BUDGET_MS: "0", + }); + try { + const exit = await waitForServeExit(failed, 15_000); + const output = failed.logs.join(""); + expect(exit).toEqual({ code: 1, signal: null }); + expect(output).toContain("Cannot connect to PostgreSQL"); + expect(output).toContain("localhost:1/envio-dev"); + expect(output).toContain("Make sure PostgreSQL is running"); + expect(output).toContain("ENVIO_PG_HOST"); + expect(output).toContain("ENVIO_PG_PORT"); + expect(output).toContain("ENVIO_PG_DATABASE"); + } finally { + if (failed.child.exitCode === null) failed.child.kill("SIGKILL"); + } + }, 30_000); + + it("reports an actionable error when the serve port is already in use", async () => { + const conflict = spawnServe(phaseConfigs.default); + try { + const exit = await waitForServeExit(conflict, 15_000); + const output = conflict.logs.join(""); + expect(exit).toEqual({ code: 1, signal: null }); + expect(output).toContain(`Port ${servePort} is already in use`); + expect(output).toContain(`lsof -ti :${servePort} | xargs kill`); + expect(output).toContain(`envio serve --port ${servePort + 1}`); + expect(output).toContain(`ENVIO_SERVE_PORT=${servePort + 1}`); + } finally { + if (conflict.child.exitCode === null) conflict.child.kill("SIGKILL"); + } + }, 30_000); + + it.runIf(process.platform !== "win32")( + "returns control to the console after Ctrl-C", + async () => { + expect(serve.child.exitCode).toBeNull(); + try { + expect(serve.child.kill("SIGINT")).toBe(true); + await expect(waitForServeExit(serve, 5_000)).resolves.toEqual({ + code: 0, + signal: null, + }); + } finally { + if (serve.child.exitCode === null) serve.child.kill("SIGKILL"); + } + }, + 15_000 + ); +}); diff --git a/packages/e2e-tests/src/differential/wsClient.ts b/packages/e2e-tests/src/differential/wsClient.ts new file mode 100644 index 0000000000..20dc5b26fe --- /dev/null +++ b/packages/e2e-tests/src/differential/wsClient.ts @@ -0,0 +1,226 @@ +/** + * Minimal GraphQL-over-WebSocket clients for both protocols Hasura serves + * on /v1/graphql: + * - "graphql-transport-ws" (modern graphql-ws): connection_init/ack, + * subscribe -> next/complete, ping/pong + * - "graphql-ws" (legacy subscriptions-transport-ws): connection_init/ack, + * start -> data/complete, ka keepalives + * + * Hand-rolled so the differential suite controls and observes every frame. + */ + +import WebSocket from "ws"; + +export type WsProtocol = "graphql-transport-ws" | "graphql-ws"; + +export interface WsFrame { + type: string; + id?: string; + payload?: unknown; +} + +export interface WsSession { + send(frame: WsFrame): void; + /** Sends an already-serialized frame, for JSON numbers JavaScript cannot + * represent without coercing them to Infinity/null. */ + sendRaw(frame: string): void; + /** Waits for the next frame matching the filter (keepalives skipped unless asked for). */ + next( + filter?: (f: WsFrame) => boolean, + timeoutMs?: number + ): Promise; + /** All frames received so far (including keepalives). */ + frames: WsFrame[]; + /** + * Throws if any data frame (`next`/`data`) arrived that no `next()` call + * consumed — a spurious extra payload the scenario never expected. + */ + assertNoUnconsumedData(): void; + /** Resolves with the close code/reason once the socket closes. */ + waitClose(timeoutMs?: number): Promise<{ code: number; reason: string }>; + close(): Promise; +} + +export async function connect( + url: string, + protocol: WsProtocol, + options: { + adminSecret?: string; + initTimeoutMs?: number; + /** Skip the connection_init/connection_ack handshake entirely. */ + skipInit?: boolean; + } = {} +): Promise { + const socket = new WebSocket(url, protocol); + const frames: WsFrame[] = []; + const waiters: { + filter: (f: WsFrame) => boolean; + resolve: (f: WsFrame) => void; + }[] = []; + let closed = false; + let closeEvent: { code: number; reason: string } | undefined; + let closeWaiter: (() => void) | undefined; + const closeWatchers: ((e: { code: number; reason: string }) => void)[] = []; + + socket.on("message", (data) => { + const frame = JSON.parse(data.toString()) as WsFrame; + frames.push(frame); + const i = waiters.findIndex((w) => w.filter(frame)); + if (i >= 0) { + const [w] = waiters.splice(i, 1); + w!.resolve(frame); + } + }); + socket.on("close", (code, reason) => { + closed = true; + closeEvent = { code, reason: reason.toString() }; + closeWaiter?.(); + for (const w of closeWatchers.splice(0)) w(closeEvent); + }); + + await new Promise((resolve, reject) => { + socket.once("open", () => resolve()); + socket.once("error", reject); + }); + + const session: WsSession = { + frames, + send(frame) { + socket.send(JSON.stringify(frame)); + }, + sendRaw(frame) { + socket.send(frame); + }, + next(filter = (f) => f.type !== "ka" && f.type !== "ping", timeoutMs = 10_000) { + const existing = frames.find((f) => !consumed.has(f) && filter(f)); + if (existing) { + consumed.add(existing); + return Promise.resolve(existing); + } + return new Promise((resolve, reject) => { + const timer = setTimeout( + () => + reject( + new Error( + `Timed out waiting for ws frame; got so far: ${JSON.stringify(frames)}` + ) + ), + timeoutMs + ); + waiters.push({ + filter, + resolve: (f) => { + clearTimeout(timer); + consumed.add(f); + resolve(f); + }, + }); + }); + }, + assertNoUnconsumedData() { + const extra = frames.filter( + (f) => !consumed.has(f) && (f.type === "next" || f.type === "data") + ); + if (extra.length > 0) { + throw new Error( + `Unconsumed extra data frame(s): ${JSON.stringify(extra)}` + ); + } + }, + waitClose(timeoutMs = 10_000) { + if (closeEvent) return Promise.resolve(closeEvent); + return new Promise((resolve, reject) => { + const timer = setTimeout( + () => + reject( + new Error( + `Timed out waiting for ws close; frames so far: ${JSON.stringify(frames)}` + ) + ), + timeoutMs + ); + closeWatchers.push((e) => { + clearTimeout(timer); + resolve(e); + }); + }); + }, + close() { + if (closed) return Promise.resolve(); + const done = new Promise((resolve) => { + closeWaiter = resolve; + }); + socket.close(); + return done; + }, + }; + const consumed = new Set(); + + if (!options.skipInit) { + const initPayload = options.adminSecret + ? { headers: { "x-hasura-admin-secret": options.adminSecret } } + : {}; + session.send({ type: "connection_init", payload: initPayload }); + await session.next( + (f) => f.type === "connection_ack", + options.initTimeoutMs ?? 10_000 + ); + } + return session; +} + +/** Subscribe and return the stream of data payloads via an async helper. */ +export interface Subscription { + /** Waits for the next data payload (protocol-normalized). */ + nextData(timeoutMs?: number): Promise; + /** Waits for the completion frame. */ + waitComplete(timeoutMs?: number): Promise; + /** Waits for a protocol error frame and returns its payload. */ + nextError(timeoutMs?: number): Promise; + stop(): void; +} + +let nextId = 1; + +export function subscribe( + session: WsSession, + protocol: WsProtocol, + payload: { query: string; variables?: Record }, + explicitId?: string +): Subscription { + const id = explicitId ?? String(nextId++); + const startType = protocol === "graphql-transport-ws" ? "subscribe" : "start"; + const dataType = protocol === "graphql-transport-ws" ? "next" : "data"; + const stopType = protocol === "graphql-transport-ws" ? "complete" : "stop"; + session.send({ type: startType, id, payload }); + + return { + async nextData(timeoutMs = 15_000) { + const frame = await session.next( + (f) => f.id === id && (f.type === dataType || f.type === "error"), + timeoutMs + ); + if (f_isError(frame)) { + throw new Error(`subscription error: ${JSON.stringify(frame.payload)}`); + } + return frame.payload; + }, + async nextError(timeoutMs = 15_000) { + const frame = await session.next( + (f) => f.id === id && f.type === "error", + timeoutMs + ); + return frame.payload; + }, + async waitComplete(timeoutMs = 15_000) { + await session.next((f) => f.id === id && f.type === "complete", timeoutMs); + }, + stop() { + session.send({ type: stopType, id }); + }, + }; + + function f_isError(f: WsFrame): boolean { + return f.type === "error"; + } +} diff --git a/packages/e2e-tests/vitest.config.ts b/packages/e2e-tests/vitest.config.ts index d9dce6f60e..0dded9733a 100644 --- a/packages/e2e-tests/vitest.config.ts +++ b/packages/e2e-tests/vitest.config.ts @@ -3,5 +3,8 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { testTimeout: 120_000, + // The differential suite needs `envio serve` + tracked Hasura; it runs + // via its own config (vitest.differential.config.ts) only. + exclude: ["**/node_modules/**", "src/differential/**"], }, }); diff --git a/packages/e2e-tests/vitest.differential.config.ts b/packages/e2e-tests/vitest.differential.config.ts new file mode 100644 index 0000000000..f6851b716a --- /dev/null +++ b/packages/e2e-tests/vitest.differential.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["src/differential/**/*.test.ts"], + testTimeout: 120_000, + hookTimeout: 180_000, + // The suite tracks/clears shared Hasura metadata — never parallelize. + fileParallelism: false, + maxWorkers: 1, + }, +}); diff --git a/packages/envio/src/Bin.res b/packages/envio/src/Bin.res index b0b3439c4a..2d81801835 100644 --- a/packages/envio/src/Bin.res +++ b/packages/envio/src/Bin.res @@ -52,8 +52,8 @@ let applyEnv = (env: dict) => let run = async args => { try { switch (await Core.runCli(args))->Null.toOption { - // Rust-only command (codegen / init / stop / docker / metrics / help / - // version / scripts) — nothing for JS to do, exit cleanly. + // Rust-only command (codegen / init / serve / stop / docker / metrics / + // help / version / scripts) — nothing for JS to do, exit cleanly. | None => () | Some(json) => switch decodeCommand(json->JSON.parseOrThrow) { diff --git a/packages/envio/src/Core.res b/packages/envio/src/Core.res index a02a200974..7a56c1b7ed 100644 --- a/packages/envio/src/Core.res +++ b/packages/envio/src/Core.res @@ -13,6 +13,7 @@ type transactionStoreCtor type addon = { getConfigJson: (~configPath: Null.t, ~directory: Null.t) => string, runCli: (~args: array, ~envioPackageDir: Null.t) => promise>, + requestShutdown: unit => unit, @as("EvmHypersyncClient") evmHypersyncClient: evmHypersyncClientCtor, @as("EvmRpcClient") @@ -190,7 +191,22 @@ let getConfigJson = (~configPath=?, ~directory=?) => { ) } +let runWithShutdownSignals = %raw(`function(run, requestShutdown) { + var onShutdown = function() { requestShutdown(); }; + process.once("SIGINT", onShutdown); + process.once("SIGTERM", onShutdown); + return run().finally(function() { + process.off("SIGINT", onShutdown); + process.off("SIGTERM", onShutdown); + }); +}`) + let runCli = args => { let addon = getAddon() - addon.runCli(~args, ~envioPackageDir=Null.make(envioPackageDir)) + let invoke = () => addon.runCli(~args, ~envioPackageDir=Null.make(envioPackageDir)) + if args->Array.some(arg => arg === "serve") { + runWithShutdownSignals(invoke, () => addon.requestShutdown()) + } else { + invoke() + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a8bdd15710..8ef6f05371 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,6 +27,9 @@ importers: '@types/node': specifier: 24.12.2 version: 24.12.2 + '@types/ws': + specifier: ^8.18.1 + version: 8.18.1 envio: specifier: file:../../packages/envio version: link:../envio @@ -39,6 +42,9 @@ importers: vitest: specifier: 4.1.0 version: 4.1.0(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(jsdom@16.7.0)(vite@7.3.1(@types/node@24.12.2)(tsx@4.21.0)) + ws: + specifier: ^8.21.0 + version: 8.21.0 packages/envio: dependencies: @@ -979,6 +985,9 @@ packages: '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} @@ -2844,8 +2853,8 @@ packages: utf-8-validate: optional: true - ws@8.19.0: - resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + ws@8.20.1: + resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -2856,8 +2865,8 @@ packages: utf-8-validate: optional: true - ws@8.20.1: - resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==} + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3606,6 +3615,10 @@ snapshots: '@types/stack-utils@2.0.3': {} + '@types/ws@8.18.1': + dependencies: + '@types/node': 24.12.2 + '@types/yargs-parser@21.0.3': {} '@types/yargs@16.0.11': @@ -4387,7 +4400,7 @@ snapshots: type-fest: 5.4.4 widest-line: 6.0.0 wrap-ansi: 9.0.2 - ws: 8.19.0 + ws: 8.20.1 yoga-layout: 3.2.1 transitivePeerDependencies: - bufferutil @@ -5678,10 +5691,10 @@ snapshots: ws@7.5.10: {} - ws@8.19.0: {} - ws@8.20.1: {} + ws@8.21.0: {} + xml-name-validator@3.0.0: {} xmlchars@2.2.0: {} diff --git a/scenarios/test_codegen/schema.graphql b/scenarios/test_codegen/schema.graphql index 1e6244300f..416a9c25d7 100644 --- a/scenarios/test_codegen/schema.graphql +++ b/scenarios/test_codegen/schema.graphql @@ -3,11 +3,15 @@ enum AccountType { USER } +"""A user of the protocol, keyed by their wallet address.""" type User { id: ID! + """The user's wallet address, lowercased.""" address: Bytes! + """The user's gravatar profile, if they have set one.""" gravatar: Gravatar updatesCountOnUserForTesting: Int! + """Tokens currently owned by this user.""" tokens: [Token!]! @derivedFrom(field: "owner") accountType: AccountType! }