[
  {
    "path": ".github/workflows/bench.yml",
    "content": "name: bench\n\npermissions:\n  contents: read\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '.github/workflows/preview.yml'\n      - 'assets/**'\n      - 'docs/**'\n      - 'example/**'\n      - 'site/**'\n      - '.gitignore'\n      - '.node-version'\n      - '.npmrc'\n      - '.nvmrc'\n      - '.prettierignore'\n      - '.prettierrc.json'\n      - '*.md'\n      - 'deno*'\n      - 'jsr*'\n      - 'LICENSE'\n      - 'outdated-typescript.d.ts'\n  pull_request:\n    paths-ignore:\n      - '.github/workflows/preview.yml'\n      - 'assets/**'\n      - 'docs/**'\n      - 'example/**'\n      - 'site/**'\n      - '.gitignore'\n      - '.node-version'\n      - '.npmrc'\n      - '.nvmrc'\n      - '.prettierignore'\n      - '.prettierrc.json'\n      - '*.md'\n      - 'deno*'\n      - 'jsr*'\n      - 'LICENSE'\n      - 'outdated-typescript.d.ts'\n  workflow_dispatch:\n\njobs:\n  typescript:\n    name: TypeScript Benchmarks\n    permissions:\n      pull-requests: write\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Run benchmarks\n        id: bench\n        run: |\n          # Run the benchmark command and capture its exit code\n          pnpm bench:ts > /tmp/benchmark_output.txt 2>&1\n          exit_code=$?\n\n          # Process the output\n          summary_output=$(cat /tmp/benchmark_output.txt | grep -v \"> \" | sed '/./,$!d')\n\n          # Set a boolean output indicating if it failed with exit code 1\n          if [ $exit_code -eq 1 ]; then\n            echo \"benchmark_failed=true\" >> $GITHUB_OUTPUT\n          else\n            echo \"benchmark_failed=false\" >> $GITHUB_OUTPUT\n          fi\n\n          echo \"full_summary<<EOF\" >> $GITHUB_OUTPUT\n          echo \"$summary_output\" >> $GITHUB_OUTPUT\n          echo \"EOF\" >> $GITHUB_OUTPUT\n\n      - name: Analyze Results\n        id: analyze\n        run: |\n          full_summary=\"${{ steps.bench.outputs.full_summary }}\"\n\n          # This powerful awk script performs two actions:\n          # 1. It finds blocks missing a Delta line and calculates it.\n          # 2. It filters for all blocks where the final delta is not zero.\n          changed_blocks=$(echo \"$full_summary\" | awk '\n          BEGIN { RS=\"\" } # Process the input in blocks separated by blank lines\n          {\n            block_text = $0 # Store the original block text\n            is_changed = 0\n\n            # If a block is missing a Delta line, calculate it\n            if ($0 ~ /Baseline:/ && $0 !~ /Delta:/) {\n              # Extract numeric values for Result and Baseline\n              match($0, /Result: ([0-9.]+)/, r)\n              match($0, /Baseline: ([0-9.]+)/, b)\n              \n              result_val = r[1]\n              baseline_val = b[1]\n              \n              # Calculate the delta, avoiding division by zero\n              if (baseline_val > 0) {\n                delta = ((result_val / baseline_val) - 1) * 100\n                # Append the newly calculated, formatted Delta line to the block\n                block_text = sprintf(\"%s\\n📊 Delta: %+.2f%%\", block_text, delta)\n              }\n            }\n            \n            # Now, check the (potentially modified) block for a non-zero delta.\n            # This works for both pre-existing deltas and the ones we just calculated.\n            if (block_text ~ /Delta:/ && block_text !~ /Delta: (\\+)?0\\.00%/) {\n              # Filter out any summary lines that are not part of a benchmark block\n              if (block_text ~ /🏌️/) {\n                print block_text \"\\n\" # Print the complete, changed block\n              }\n            }\n          }')\n\n          if [ -n \"$changed_blocks\" ]; then\n            echo \"has_changes=true\" >> $GITHUB_OUTPUT\n            echo \"changed_blocks<<EOF\" >> $GITHUB_OUTPUT\n            echo \"$changed_blocks\" >> $GITHUB_OUTPUT\n            echo \"EOF\" >> $GITHUB_OUTPUT\n          else\n            echo \"has_changes=false\" >> $GITHUB_OUTPUT\n          fi\n\n      - name: PR Comment on Changes\n        if: steps.analyze.outputs.has_changes == 'true' && github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false\n        uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1\n        with:\n          comment-tag: typescript-benchmarks\n          message: |\n            <details>\n            <summary>⏱️ <strong>Benchmark changes detected</strong> following ${{ github.event.pull_request.head.sha }}</summary>\n\n            The following benchmarks have changed from the baseline:\n            ```\n            ${{ steps.analyze.outputs.changed_blocks }}\n            ```\n            </details>\n\n      - name: PR Comment on No Changes\n        if: steps.analyze.outputs.has_changes == 'false' && github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false\n        uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1\n        with:\n          comment-tag: typescript-benchmarks\n          message: ✅ ⏱️ **No benchmark changes detected** following ${{ github.event.pull_request.head.sha }}.\n\n      - name: Fail job if benchmark command failed\n        if: steps.bench.outputs.benchmark_failed == 'true'\n        run: |\n          echo \"Benchmark command failed with exit code 1\"\n          exit 1\n"
  },
  {
    "path": ".github/workflows/compare.yml",
    "content": "name: compare llms-full.txt\n\npermissions:\n  contents: read\n\non:\n  pull_request:\n    paths:\n      - '.github/workflows/compare.yml'\n      - 'site/**'\n  workflow_dispatch:\n\njobs:\n  build-current:\n    name: Build current branch\n    runs-on: ubuntu-latest\n    outputs:\n      artifact-name: current-llms-full-txt\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Build\n        working-directory: site\n        run: pnpm build\n\n      - name: Upload current build artifact\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: current-llms-full-txt\n          path: site/build/llms-full.txt\n\n  build-target:\n    name: Build target branch\n    runs-on: ubuntu-latest\n    outputs:\n      artifact-name: target-llms-full-txt\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Checkout target branch and build\n        run: |\n          TARGET_BRANCH=${{ github.event.pull_request.base.ref || 'master' }}\n          git fetch origin $TARGET_BRANCH:$TARGET_BRANCH\n          git checkout $TARGET_BRANCH\n          pnpm install\n          cd site && pnpm build\n\n      - name: Upload target build artifact\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: target-llms-full-txt\n          path: site/build/llms-full.txt\n\n  diff:\n    name: Diff current branch vs. target branch\n    runs-on: ubuntu-latest\n    needs: [build-current, build-target]\n\n    steps:\n      - name: Download current build\n        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1\n        with:\n          name: current-llms-full-txt\n          path: current/\n\n      - name: Download target build\n        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1\n        with:\n          name: target-llms-full-txt\n          path: target/\n\n      - name: Diff current vs. target\n        uses: LouisBrunner/diff-action@9ea7b75986aa27143ad4928974c98a5a1bd92170 # v2.2.0\n        with:\n          mode: addition\n          new: current/llms-full.txt\n          old: target/llms-full.txt\n          output: diff-llms-full.txt\n          tolerance: mixed\n"
  },
  {
    "path": ".github/workflows/preview.yml",
    "content": "name: preview\n\npermissions:\n  contents: read\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    paths:\n      - '**/*'\n      - '!.github/workflows/*.yml'\n      - '.github/workflows/preview.yml'\n      - '!assets/**'\n      - '!docs/**'\n      - '!example/**'\n      - '!site/**'\n      - '!test/**'\n      - '!.node-version'\n      - '!.nvmrc'\n      - '!.prettierignore'\n      - '!.prettierrc.json'\n      - '!*.md'\n      - '!deno.check*'\n      - '!deno.lint.json'\n      - '!docker-compose.yml'\n      - '!jsr.json'\n      - '!LICENSE'\n\njobs:\n  release:\n    name: Release preview build\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Build\n        run: pnpm build\n\n      - name: Release preview version\n        run: pnpx pkg-pr-new@0.0.61 publish --template './example'\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "# https://docs.npmjs.com/trusted-publishers#github-actions-configuration\nname: publish\n\non:\n  push:\n    tags:\n      - 'v*'\n\npermissions:\n  contents: read\n  id-token: write # Required for OIDC\n\njobs:\n  npm:\n    if: github.repository == 'kysely-org/kysely'\n    environment: release\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden the runner (Audit all outbound calls)\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          fetch-depth: 0 # Need full history to check branch ancestry\n\n      - name: verify tag format and branch\n        run: |\n          # Validate ref_name format before assignment\n          if [[ ! \"${{ github.ref_name }}\" =~ ^v[0-9]+\\.[0-9]+\\.[0-9]+$ ]]; then\n            echo \"Error: tag does not follow semver!\"\n            exit 1\n          fi\n\n          TAG=\"${{ github.ref_name }}\"\n\n          # Check if tag points to a commit that exists on master branch\n          TAG_COMMIT=$(git rev-list -n 1 \"$TAG\")\n          if ! git merge-base --is-ancestor \"$TAG_COMMIT\" origin/master; then\n            echo \"Error: tag is not based on master branch\"\n            exit 1\n          fi\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: pnpm\n          node-version: lts/*\n          registry-url: https://registry.npmjs.org/\n\n      - name: verify package version\n        run: |\n          TAG=\"${{ github.ref_name }}\"\n          VERSION=\"${TAG#v}\"\n\n          # Get version from package.json safely (parse as JSON, don't execute)\n          PACKAGE_VERSION=$(node -p \"JSON.parse(require('node:fs').readFileSync('./package.json', 'utf8')).version\")\n\n          # Validate version format: must be MAJOR.MINOR.PATCH\n          if [[ ! \"$PACKAGE_VERSION\" =~ ^[0-9]+\\.[0-9]+\\.[0-9]+$ ]]; then\n            echo \"Error: package.json version does not follow semver!\"\n            exit 1\n          fi\n\n          # Verify versions match\n          if [[ \"$VERSION\" != \"$PACKAGE_VERSION\" ]]; then\n            echo \"Error: tag and package.json version don't match!\"\n            exit 1\n          fi\n\n      - name: Install dependencies\n        run: npm i -g npm@^11.5.2 && pnpm i --frozen-lockfile --prefer-offline\n\n      - name: Publish\n        run: pnpm publish --no-git-checks # the workflow runs in a detached head state, so git checks fail\n\n  jsr:\n    needs: npm\n    environment: release\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden the runner (Audit all outbound calls)\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm i\n\n      - name: Prepare for publish\n        run: pnpm script:remove-global-augmentations\n\n      - name: publish\n        run: pnpm jsr publish --allow-dirty\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: test\n\npermissions:\n  contents: read\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - '**/*'\n      - '!.github/workflows/*.yml'\n      - '.github/workflows/test.yml'\n      - '!assets/**'\n      - '!docs/**'\n      - '!example/**'\n      - '!site/**'\n      - '!.node-version'\n      - '!.nvmrc'\n      - '!.prettierignore'\n      - '!.prettierrc.json'\n      - '!*.md'\n      - '!LICENSE'\n  pull_request:\n    paths:\n      - '**/*'\n      - '!.github/workflows/*.yml'\n      - '.github/workflows/test.yml'\n      - '!assets/**'\n      - '!docs/**'\n      - '!example/**'\n      - '!site/**'\n      - '!.node-version'\n      - '!.nvmrc'\n      - '!.prettierignore'\n      - '!.prettierrc.json'\n      - '!*.md'\n      - '!LICENSE'\n  workflow_dispatch:\n\njobs:\n  node:\n    strategy:\n      fail-fast: false\n      matrix:\n        # https://endoflife.date/nodejs\n        node-version: [20.x, 22.x, 24.x, 25.x]\n        with-transformer: [false, true]\n    runs-on: ubuntu-latest\n\n    name: Node.js (${{ matrix.node-version }})${{ matrix.with-transformer && ' /w transformer' || '' }}\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: ${{ matrix.node-version }}\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Run docker compose\n        run: docker compose up -d\n\n      - name: Run node tests\n        run: ${{ matrix.with-transformer && 'TEST_TRANSFORMER=1 ' || '' }}pnpm test\n\n      - name: Run esbuild test\n        if: ${{ !matrix.with-transformer }}\n        run: pnpm test:esbuild\n\n  deno:\n    name: Deno\n    runs-on: ubuntu-latest\n\n    strategy:\n      fail-fast: false\n      matrix:\n        # https://endoflife.date/deno\n        deno-version: [2.5.x]\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Use Deno ${{ matrix.deno-version }}\n        uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3\n        with:\n          deno-version: ${{ matrix.deno-version }}\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Run docker compose\n        run: docker compose up -d\n\n      - name: Build\n        run: pnpm build\n\n      - name: Run deno tests\n        run: pnpm test:deno\n\n      - name: Lint for Deno/JSR\n        run: pnpm lint:deno\n\n  bun:\n    name: Bun\n    runs-on: ubuntu-latest\n\n    strategy:\n      fail-fast: false\n      matrix:\n        bun-version: [1.1.44, 1.2.23, 1.3]\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Use Bun ${{ matrix.bun-version }}\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0\n        with:\n          bun-version: ${{ matrix.bun-version }}\n\n      - name: Run docker compose\n        run: docker compose up -d\n\n      - name: Run bun tests\n        run: pnpm test:bun\n\n  browser:\n    name: Browser\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Install playwright\n        run: pnpm playwright install chromium\n\n      - name: Run browser tests\n        run: pnpm test:browser\n\n  cloudflare-workers:\n    name: Cloudflare Workers\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Run docker compose\n        run: docker compose up -d\n\n      - name: Run cloudflare workers test\n        run: pnpm test:cloudflare-workers\n\n  older-typescript-version:\n    name: Older TypeScript version\n    runs-on: ubuntu-latest\n\n    strategy:\n      fail-fast: false\n      matrix:\n        typescript-version: [\n            ~4.6.0, # 28.2.2022 https://devblogs.microsoft.com/typescript/announcing-typescript-4-6/\n            ~4.7.0, # 24.5.2022 https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/\n            ~4.8.0, # 25.8.2022 https://devblogs.microsoft.com/typescript/announcing-typescript-4-8/\n            ~4.9.0, # 15.11.2022 https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/\n            ~5.0.0, # 16.3.2023 https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/\n            ~5.2.0, # 24.8.2023 https://devblogs.microsoft.com/typescript/announcing-typescript-5-1/ https://devblogs.microsoft.com/typescript/announcing-typescript-5-2/\n            ~5.3.0, # 20.11.2023 https://devblogs.microsoft.com/typescript/announcing-typescript-5-3/\n            ~5.4.0, # 6.3.2024 https://devblogs.microsoft.com/typescript/announcing-typescript-5-4/\n            ~5.8.0, # 28.2.2025 https://devblogs.microsoft.com/typescript/announcing-typescript-5-5/ https://devblogs.microsoft.com/typescript/announcing-typescript-5-6/ https://devblogs.microsoft.com/typescript/announcing-typescript-5-7/ https://devblogs.microsoft.com/typescript/announcing-typescript-5-8/\n            # ~5.9.0, # 1.8.2025 https://devblogs.microsoft.com/typescript/announcing-typescript-5-9/\n          ]\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Run build with newer TypeScript\n        run: pnpm build\n\n      - name: Set TypeScript and TSD versions\n        run: |\n          TS_VERSION=\"${{ matrix.typescript-version }}\"\n          echo \"TS_VERSION=$TS_VERSION\" >> $GITHUB_ENV\n          TSD_VERSION=$(echo '{\"~4.6.0\":\"0.20.0\", \"~4.7.0\":\"0.22.0\", \"~4.8.0\":\"0.24.1\", \"~4.9.0\":\"0.27.0\", \"~5.0.0\":\"0.28.1\", \"~5.2.0\":\"0.29.0\", \"~5.3.0\":\"0.30.7\", \"~5.4.0\":\"0.31.2\", \"~5.8.0\":\"0.32.0\", \"~5.9.0\":\"0.33.0\"}' | jq -r --arg key \"$TS_VERSION\" '.[$key]')\n          echo \"TSD_VERSION=$TSD_VERSION\" >> $GITHUB_ENV\n\n      - name: Install Typescript (${{ env.TS_VERSION }}) and TSD (${{ env.TSD_VERSION }})\n        run: pnpm i -D typescript@${{ env.TS_VERSION }} tsd@${{ env.TSD_VERSION }}\n\n      - name: Exclude non-backward compatible tests\n        run: pnpm script:exclude-test-files-for-backwards-compat\n\n      - name: Run tests with older TypeScript version\n        run: pnpm test:typings${{ env.TS_VERSION != '~4.6.0' && env.TS_VERSION != '~4.7.0' && ' && pnpm test:node:build' || '' }}\n\n  jsdocs:\n    name: JSDocs\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Use Deno\n        uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3\n        with:\n          deno-version: 2.x\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Build\n        run: pnpm build\n\n      - name: Type-check JSDocs code blocks\n        run: pnpm test:jsdocs\n\n  typescript-native:\n    name: TypeScript Native\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm i\n\n      - name: Build\n        run: pnpm build\n\n      - name: Run TypeScript Native tests\n        run: pnpx @typescript/native-preview --project ./test/node/tsconfig.json\n\n  typescript-composite:\n    name: TypeScript Composite\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm i\n\n      - name: Test\n        working-directory: test/composite-ts\n        run: npm i && npm run check:types\n\n  jsr:\n    name: JSR\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0\n\n      - name: Use Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          cache: 'pnpm'\n          node-version: lts/*\n\n      - name: Install dependencies\n        run: pnpm i\n\n      - name: Prepare for publish\n        run: pnpm script:remove-global-augmentations\n\n      - name: Dry-run jsr publish\n        run: pnpm jsr publish --allow-dirty --dry-run\n"
  },
  {
    "path": ".gitignore",
    "content": "dist\n/helpers\n/test/browser/bundle.js\nnode_modules\n.vscode\n.idea\ntsconfig.tsbuildinfo\n"
  },
  {
    "path": ".mocharc.js",
    "content": "const { isCI } = require('std-env')\n\nmodule.exports = {\n  forbidOnly: isCI,\n}\n"
  },
  {
    "path": ".node-version",
    "content": "22\n"
  },
  {
    "path": ".npmrc",
    "content": "# so we don't have to `-w` anytime we bump root workspace dependencies.\nignore-workspace-root-check=true\n"
  },
  {
    "path": ".nvmrc",
    "content": "lts/*\n"
  },
  {
    "path": ".prettierignore",
    "content": "*.md"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\"\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# ~~Contributor Covenant Code of Conduct~~ Kysely Code of Conduct\n\n## Our Pledge\n\n~~We as members, contributors, and leaders pledge to make participation in our~~\n~~community a harassment-free experience for everyone, regardless of age, body~~\n~~size, visible or invisible disability, ethnicity, sex characteristics, gender~~\n~~identity and expression, level of experience, education, socio-economic status,~~\n~~nationality, personal appearance, race, religion, or sexual identity~~\n~~and orientation.~~\n\n~~We pledge to act and interact in ways that contribute to an open, welcoming,~~\n~~diverse, inclusive, and healthy community.~~\n\nDon't be an asshole.\nYou are not entitled to other people's time, energy, or attention.\n\nThat's it. That's the pledge.\n\n## Our Standards\n\n~~Examples of behavior that contributes to a positive environment for our~~\n~~community include:~~\n\n~~* Demonstrating empathy and kindness toward other people~~\n~~* Being respectful of differing opinions, viewpoints, and experiences~~\n~~* Giving and gracefully accepting constructive feedback~~\n~~* Accepting responsibility and apologizing to those affected by our mistakes,~~\n  ~~and learning from the experience~~\n~~* Focusing on what is best not just for us as individuals, but for the~~\n  ~~overall community~~\n\n~~Examples of unacceptable behavior include:~~\n\n~~* The use of sexualized language or imagery, and sexual attention or~~\n  ~~advances of any kind~~\n~~* Trolling, insulting or derogatory comments, and personal or political attacks~~\n~~* Public or private harassment~~\n~~* Publishing others' private information, such as a physical or email~~\n  ~~address, without their explicit permission~~\n~~* Other conduct which could reasonably be considered inappropriate in a~~\n  ~~professional setting~~\n\nDon't be an asshole.\nYou are not entitled to other people's time, energy, or attention.\n\nExamples of being an asshole or entitled include:\n\n* Probably not the best idea to come in complaining and not having minimal respect to develop some basic sentences.\n  > what is the migration_lock ?? why we have this in the database - https://github.com/kysely-org/kysely/issues/973\n* Probably not the best idea to attack the maintainer after he answered succinctly (out of character) for whatever reason (context switch? busy?).\n  > You got any more of them there examples buster? - https://github.com/kysely-org/kysely/issues/677#issuecomment-2019876074\n* Probably not the best idea to come in all yelling and demanding stuff.\n  > NO documentation about error handling!!!!\n  > I am really confused that the docs doesnt have anything about error handling\n  > this is a mandataory things to add!! - https://github.com/kysely-org/kysely/issues/1217\n* Probably not the best idea to tone police the maintainer after he spent time explaining library philosophy, and to publicly refuse to contribute something you demanded.\n  > I'm sorry fella but with your tone I really don't feel like it. Good luck - https://github.com/kysely-org/kysely/issues/709#issuecomment-1727617260\n* Probably not the best idea to question the maintainer's decisions after properly answering your question, and to be entitled for JavaScript skill issue help after the issue is closed.\n  > I don't understand your answer and closing the issue. - https://github.com/kysely-org/kysely/issues/527#issuecomment-1577383794\n* Probably not the best idea to jump into closed issues and be entitled to other people's efforts.\n  > why on earth there is no mention of this in the documentation? - https://github.com/kysely-org/kysely/issues/649#issuecomment-2430854835\n* Probably not the best idea to not search existing issues, and then ask the maintainer to spend time doing it.\n  > could you please provide numbers of duplicated issues to explore the topic? - https://github.com/kysely-org/kysely/issues/762#issuecomment-1801951960\n* Probably not the best idea to sarcastically suggest the maintainer is not helpful while using his hard work for free.\n  > Most helpful man in the world - https://github.com/kysely-org/kysely/issues/762#issuecomment-2404599281\n* Probably not the best idea to side with the asshole/entitled by upvoting them or downvoting us.\n\n  ![image](https://github.com/user-attachments/assets/ca6efd57-d8db-428a-a274-7b45b380887f)\n  ![image](https://github.com/user-attachments/assets/62356fa3-7cea-4b82-9967-d56c76f0beee)\n\n\n\n## Enforcement Responsibilities\n\n~~Community leaders are responsible for clarifying and enforcing our standards of~~\n~~acceptable behavior and will take appropriate and fair corrective action in~~\n~~response to any behavior that they deem inappropriate, threatening, offensive,~~\n~~or harmful.~~\n\n~~Community leaders have the right and responsibility to remove, edit, or reject~~\n~~comments, commits, code, wiki edits, issues, and other contributions that are~~\n~~not aligned to this Code of Conduct, and will communicate reasons for moderation~~\n~~decisions when appropriate.~~\n\nWe are here in our free time. We are not getting paid to serve and please you.\n\nWe will not tolerate assholes or entitled behavior.\n\nWe are capable of banning you from the GitHub organization, Discord server, or any \nother community space we manage. Don't make us do it.\n\n## Scope\n\n~~This Code of Conduct applies within all community spaces, and also applies when~~\n~~an individual is officially representing the community in public spaces.~~\n~~Examples of representing our community include using an official e-mail address,~~\n~~posting via an official social media account, or acting as an appointed~~\n~~representative at an online or offline event.~~\n\nRelevant to all repositories in the Kysely GitHub organization, the Kysely Discord \nserver, and any other community space managed by Kysely.\n\n## Enforcement\n\n~~Instances of abusive, harassing, or otherwise unacceptable behavior may be~~\n~~reported to the community leaders responsible for enforcement at~~\n~~Kysely's GitHub repositories and Discord server.~~\n~~All complaints will be reviewed and investigated promptly and fairly.~~\n\n~~All community leaders are obligated to respect the privacy and security of the~~\n~~reporter of any incident.~~\n\nReport to us anyone who is being an asshole or entitled.\nWe will take appropriate action if necessary.\n\n## Enforcement Guidelines\n\n~~Community leaders will follow these Community Impact Guidelines in determining~~\n~~the consequences for any action they deem in violation of this Code of Conduct:~~\n\nWe might do these things:\n\n~~### 1. Correction~~\n\n**Community Impact**: ~~Use of inappropriate language or other behavior deemed~~\n~~unprofessional or unwelcome in the community.~~\n\nSomeone being an asshole or entitled.\n\n**Consequence**: ~~A private, written warning from community leaders, providing~~\n~~clarity around the nature of the violation and an explanation of why the~~\n~~behavior was inappropriate. A public apology may be requested.~~\n\nWe might return the favor (we're not perfect), ignore you, edit/close/lock/delete \nyour post/comment, or ban you. There is no strike system.\n\n~~### 2. Warning~~\n\n~~**Community Impact**: A violation through a single incident or series~~\n~~of actions.~~\n\n~~**Consequence**: A warning with consequences for continued behavior. No~~\n~~interaction with the people involved, including unsolicited interaction with~~\n~~those enforcing the Code of Conduct, for a specified period of time. This~~\n~~includes avoiding interactions in community spaces as well as external channels~~\n~~like social media. Violating these terms may lead to a temporary or~~\n~~permanent ban.~~\n\n~~### 3. Temporary Ban~~\n\n~~**Community Impact**: A serious violation of community standards, including~~\n~~sustained inappropriate behavior.~~\n\n~~**Consequence**: A temporary ban from any sort of interaction or public~~\n~~communication with the community for a specified period of time. No public or~~\n~~private interaction with the people involved, including unsolicited interaction~~\n~~with those enforcing the Code of Conduct, is allowed during this period.~~\n~~Violating these terms may lead to a permanent ban.~~\n\n~~### 4. Permanent Ban~~\n\n~~**Community Impact**: Demonstrating a pattern of violation of community~~\n~~standards, including sustained inappropriate behavior,  harassment of an~~\n~~individual, or aggression toward or disparagement of classes of individuals.~~\n\n~~**Consequence**: A permanent ban from any sort of public interaction within~~\n~~the community.~~\n\n## ~~Attribution~~\n\n~~This Code of Conduct is adapted from the [Contributor Covenant][homepage],~~\n~~version 2.0, available at~~\n~~https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.~~\n\n~~Community Impact Guidelines were inspired by [Mozilla's code of conduct~~\n~~enforcement ladder](https://github.com/mozilla/diversity).~~\n\n~~[homepage]: https://www.contributor-covenant.org~~\n\n~~For answers to common questions about this code of conduct, see the FAQ at~~\n~~https://www.contributor-covenant.org/faq. Translations are available at~~\n~~https://www.contributor-covenant.org/translations.~~\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contribution Guidelines\n\nWanna contribute to Kysely or other libraries within the [kysely-org](https://github.com/kysely-org) organization?\n\nYou're awesome! 🤗\n\n## 😕 How Can I Contribute?\n\n## 📢 By Spreading the Word\n\nIf you like what we're building here, please: \n\n1. Tell your friends, co-workers, family, neighbors, followers, agent markdowns, etc.\n1. Speak about it in meetups and conferences. (if you need help with the presentation, please ask on Discord!).\n\nThere is no company behind this organization and project. We do this in our free time and cannot advertise it\nall by ourselves. Companies have dedicated devrel teams doing all that work, other projects might have community\nmanagers or full-time developers with the capacity to also handle social media and meetups with higher frequency.\n\nMore people using Kysely eventually means:\n\n1. less bugs left unreported and unsolved.\n1. high chance people share workarounds.\n1. more data points for innovation.\n1. more people who might contribute and push this thing even further.\n1. it becomes a standard part of the Node.js/Bun/Deno developer's toolbox so you'll happily stumble upon it\n   in future codebases you'll join, or it'll be easier to get buy-in from co-workers/leadership.\n\n## 🤝 By Helping People in Issues or on Discord\n\nWe need all the help we can get with supporting the community, answering questions, triaging! \n\nIf you've been using the library for a while, or know a thing or two about SQL, and specific databases, don't \nbe shy about it!\n\n## 🐛 By Submitting Issues (Bugs, Enhancement Ideas, Questions) or Opening threads on Discord\n\nPlease use search and make sure an existing **open** issue or thread doesn't exist before submitting. If an existing\nissue is only somewhat relevant, please submit a new issue and reference the old one instead of commenting\non the existing one. Let us label your new issue as `duplicate` if it is the same thing - it's fine! If it's not \nthe same thing and you commented on another issue, it makes it harder to track on our end.\n\nIf possible/relevant, please provide a [playground link](https://kyse.link), Stackblitz OR a public git repository that \nreproduces the issue.\n\nPlease provide the exact error/warning texts you're getting. \"this doesn't work\" or \"this throws an error\"\nare not helping us help you.\n\nDon't be an asshole. Don't demand support/service from us.\n\n## ⌨️ With Code!\n\n### 📘 Documentation Code Contributions\n\nPull requests are always welcome! \n\nThe [kysely.dev](https://kysely.dev) application is located @ [/site](https://github.com/kysely-org/kysely/tree/master/site).\n\nIt is a pretty standard [docusaurus](https://docusaurus.io/) application.\n\nThe code examples are extracted, using a custom script (see `\"script:generate-site-examples\"` @ [package.json](https://github.com/kysely-org/kysely/blob/master/package.json)), \nand custom annotations, from [JSDocs](https://jsdoc.app/) comments in the source code @ [/src](https://github.com/kysely-org/kysely/tree/master/src).\nIf you need to change an existing code example, please do so in the source code AND then run the script.\n_TODO: explain how to add a new code example._\n\nIf it is a big change (lots of lines of code OR files involved), please get a conversation going on an issue or on \nDiscord before starting work on it.\n\n### 🧙 Implementation Code Contributions (Bugfixes, Enhancements [Existing or New Features])\n\nPull requests (PRs) are welcome, BUT since:\n\n1. Our time and capacity as maintainers are limited.\n1. Your time is limited.\n1. Your motivation and morale is important to us.\n1. Onboarding in a new highly opinionated open-source project can be challenging.\n\nWe need a process in place:\n\n1. To make sure only things that have a good chance of being accepted are worked on. We hate saying \"no\".\n1. To make sure that things that are being worked on don't result in too much back-and-forth between authors and maintainers.\n   We hate seeing these things drag on for a long time, and we know how frustrating it is on your end.\n1. To make sure there's no pressure on you when you take on a task.\n1. To make sure there's a clear understanding of who is working on what to avoid redundancies and conflicts.\n\n#### The Process\n\nHere is the gist of it:\n\n1. If an issue on the subject **doesn't exist** yet, **submit** one. If you want to work on it, **ask** to be **assigned**\n   to it in the issue **description**, in the **comments**, OR on **Discord**.\n1. If an issue on the subject **exists** and is labeled with `bug` OR (`enhancement` AND `greenlit`\\* OR even `good first issue`\\**):\n   1. If there is a pull request (**PR**) **linked** to it:\n      1. If the **PR** is **stale** (a few months without new commits or comments from the PR author OR Kysely maintainers),\n         **ask** to be **assigned** to it and continue work on the PR.\n      1. If the **PR** is **not stale**, you can still offer some review comments, or **ask** to **pair** up with the PR author.\n   1. If there is **no PR linked** to it and a person is **already assigned** to it:\n      1. If the assignment is stale (a few weeks without a PR opened after the person was assigned to the issue), ask\n         to be assigned to the issue in the comments OR on Discord.\n      1. If the assignment is not stale, it's OK to ask the assignee if they'll be willing to pair up.\n   1. If there is no PR linked to it and no assignee, ask to be assigned to it in the comments OR on Discord.\n   \n_\\* an issue that was reviewed by the maintainers and would be nice to get a pull request for from the community._\n\n_\\** an issue that was reviewed by the maintainers and would be a nice opportunity to onboard an open-source newbie\n  into the codebase._\n\nOnce you're assigned to an issue, you can start working on your code changes. It's best to ask questions\nin the issue or on Discord as early as possible, and even share your progress with the maintainers and community via a \ndraft (WIP) pull request.\n\nWe will close surprise pull requests that are not related to an existing issue or the pull request submitter is not\nassigned to the issue.\n\nWe will close pull requests where the changes are too far from acceptable. Such cases are a waste of time for us to\neven begin to comment on. You can ask for quick informal feedback on Discord in such cases and submit another pull\nrequest with better changes later.\n\n#### Style/Design Philosophy\n\n* Kysely should have zero dependencies.\n\n* Kysely should work in all JavaScript environments (node.js, deno & modern browsers), \neven though the main focus is node.js.\n\n* Everything is immutable.\n\n* The API should be as close to writing raw SQL as possible while still providing \ntype safety.\n\n* Everything outside of dialect implementations is dialect-agnostic.\n\n* Everything is tested.\n\n    * Functionality - No mocks. Everything is tested against real database instances.\n    No partial testing. If a sql \"thing\" is supported by some databases, test it\n    against all of them.\n\n    * Types - We're a type-safe package, you get the idea.\n\n* Everything consumer-facing should be documented.\n\n* Everything is type-safe. Things that cannot be implemented in a way that is safe \nfor all cases, are best left for consumers to implement.\n\n* Most features should have escape hatches.\n\n* Less is more.\n\n#### Getting Started\n\n1. fork kysely.\n\n1. clone your fork.\n\n1. install Node.js (preferably the latest even-numbered version). we recommend using [`fnm`](https://github.com/Schniz/fnm) for managing Node.js versions.\n\n1. install `corepack` by running `npm i -g corepack` in your terminal.\n\n1. run `corepack enable` in your terminal.\n\n1. `cd` into the repository.\n\n1. run `corepack install` in your terminal to install the exact package manager and version used in this project.\n\n1. run `pnpm i` in your terminal to install dependencies. if `pnpm` tells you it ignored a `postinstall` script from some package - tells us immediately via issue or Discord - this is a security concern!\n\n1. create a branch (we don't care about naming).\n\n1. create a draft pull request. link the relevant issue by referring to it in the \nPR's description. E.g. `closes #123` will link the PR to issue/pull request #123.\n\n1. implement your changes.\n\n#### Testing\n\n1. write functionality tests @ [/test/node](https://github.com/kysely-org/kysely/tree/master/test/node).\n\n1. write typings tests @ [/test/typings](https://github.com/kysely-org/kysely/tree/master/test/typings)\n\n1. install Docker.\n\n1. run `docker compose up -d` in your terminal to spin up database instances.\n\n1. run `pnpm test` in your terminal.\n"
  },
  {
    "path": "FUNDING.md",
    "content": "# Funding\n\nKysely is an MIT-licensed open-source project and is completely free to use - and will remain so.\n\nKysely is a labor of love. We do this in our free time.\n\nWe do not accept donations.\n\n- Getting paid for open-source won't make us put more time and effort into open-source.\n  We have family, friends, and other hobbies and interests.\n\n- We work in the tech industry, full-time, as software developers. We are comfortable as-is.\n\n- We don't believe in freelance open-source as a stable source of income for the long term.\n  We have mouths to feed, and careers to maintain.\n\n- Sponsored projects tend to be affected by big sponsors. We want to keep Kysely away\n  from companies' and VCs' opinions and business needs.\n\n- Kysely is escapism for us. We don't want it to feel like another job.\n\n\nInstead of donating to us, we encourage you to support meaningful causes or other open-source projects in need of funding.\n\nThank you for supporting Kysely through your usage, contributions, and feedback.\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2022 Sami Koskimäki\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://stand-with-ukraine.pp.ua)\n\n[![NPM Version](https://img.shields.io/npm/v/kysely?style=flat&label=latest)](https://github.com/kysely-org/kysely/releases/latest)\n[![Tests](https://github.com/kysely-org/kysely/actions/workflows/test.yml/badge.svg)](https://github.com/kysely-org/kysely)\n[![License](https://img.shields.io/github/license/kysely-org/kysely?style=flat)](https://github.com/kysely-org/kysely/blob/master/LICENSE)\n[![Issues](https://img.shields.io/github/issues-closed/kysely-org/kysely?logo=github)](https://github.com/kysely-org/kysely/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc)\n[![Pull Requests](https://img.shields.io/github/issues-pr-closed/kysely-org/kysely?label=PRs&logo=github&style=flat)](https://github.com/kysely-org/kysely/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc)\n![GitHub contributors](https://img.shields.io/github/contributors/kysely-org/kysely)\n[![NPM Downloads](https://img.shields.io/npm/dw/kysely?logo=npm)](https://www.npmjs.com/package/kysely)\n[![JSR Downloads](https://jsr.io/badges/@kysely/kysely/weekly-downloads)](https://jsr.io/@kysely/kysely)\n[![JSR Score](https://jsr.io/badges/@kysely/kysely/score)](https://jsr.io/@kysely/kysely)\n\n###### Join the discussion ⠀⠀⠀⠀⠀⠀⠀ \n[![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?style=flat&logo=discord&logoColor=white)](https://discord.gg/xyBJ3GwvAm)\n[![Bluesky](https://img.shields.io/badge/Bluesky-0285FF?style=flat&logo=Bluesky&logoColor=white)](https://bsky.app/profile/kysely.dev)\n\n###### Get started\n[![Postgres](https://img.shields.io/badge/postgres-%23316192.svg?style=flat&logo=postgresql&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=postgresql)\n[![MySQL](https://img.shields.io/badge/mysql-4479A1.svg?style=flat&logo=mysql&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=mysql)\n[![MicrosoftSQLServer](https://img.shields.io/badge/Microsoft%20SQL%20Server-CC2927?style=flat&logo=microsoft%20sql%20server&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=mssql)\n[![SQLite](https://img.shields.io/badge/sqlite-%2307405e.svg?style=flat&logo=sqlite&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=sqlite)\n& more!\n\n# [Kysely](https://kysely.dev)\n\nKysely (pronounce “Key-Seh-Lee”) is a type-safe and autocompletion-friendly [TypeScript](https://www.typescriptlang.org/) [SQL](https://en.wikipedia.org/wiki/SQL) query builder.\nInspired by [Knex.js](http://knexjs.org/). Mainly developed for [Node.js](https://nodejs.org/en/) but also\nruns on all other [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) environments like [Deno](https://deno.com/), [Bun](https://bun.sh/), [Cloudflare Workers](https://workers.cloudflare.com/)\nand web browsers.\n\n![](https://github.com/kysely-org/kysely/blob/master/assets/demo.gif)\n\nKysely makes sure you only refer to tables and columns that are visible to the part of the query\nyou're writing. The result type only has the selected columns with correct types and aliases. As an\nadded bonus you get autocompletion for all that stuff.\n\nAs shown in the gif above, through the pure magic of modern TypeScript, Kysely is even able to parse\nthe alias given to `pet.name` and add the `pet_name` column to the result row type. Kysely is able to infer\ncolumn names, aliases and types from selected subqueries, joined subqueries, `with` statements and pretty\nmuch anything you can think of.\n\nOf course there are cases where things cannot be typed at compile time, and Kysely offers escape\nhatches for these situations. See the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html)\nand the [DynamicModule](https://kysely-org.github.io/kysely-apidoc/classes/DynamicModule.html#ref) for more info.\n\nAll API documentation is written in the typing files and you can simply hover over the module, class\nor method you're using to see it in your IDE. The same documentation is also hosted [here](https://kysely-org.github.io/kysely-apidoc/).\n\nIf you start using Kysely and can't find something you'd want to use, please open an issue or join our\n[Discord server](https://discord.gg/xyBJ3GwvAm).\n\n# Getting started\n\nPlease visit our documentation site [kysely.dev](https://kysely.dev) to get started. We also have a comprehensive\nAPI documentation hosted [here](https://kysely-org.github.io/kysely-apidoc/), but you can access the same\ndocumentation in your IDE by hovering over a class/method/property/whatever.\n\n# Core team\n\n## Project leads\n\nResponsible for project direction, API design, maintenance, code reviews, community support, documentation, and working on some of the most \nimpactful/challenging things.\n\n<table>\n    <tbody>\n        <tr>\n            <td align=\"center\">\n                <a href=\"https://github.com/koskimas\">\n                    <img src=\"https://avatars.githubusercontent.com/u/846508?v=4?s=100\" width=\"100px;\" alt=\"\"/>\n                    <br />\n                    Sami Koskimäki\n                </a>\n                <br />\n                (the <a href=\"https://web.archive.org/web/20211203210043/https://www.jakso.me/blog/kysely-a-type-safe-sql-query-builder-for-typescript\">author</a>)\n            </td>\n            <td align=\"center\">\n                <a href=\"https://github.com/igalklebanov\">\n                    <img src=\"https://avatars.githubusercontent.com/u/14938291?v=4&s=100\" width=\"100px;\" alt=\"\"/>\n                    <br />\n                    Igal Klebanov\n                </a>\n                <br />\n                (the <a href=\"https://github.com/kysely-org/kysely/pull/1414#issuecomment-2781281996\">dynamo</a>)\n            </td>\n        </tr>\n    </tbody>\n</table>\n\n## Honorable mentions\n\nPeople who had special impact on the project and its growth.\n\n<table>\n    <tbody>\n        <tr>\n            <td align=\"center\">\n                <a href=\"https://github.com/fhur\">\n                    <img src=\"https://avatars.githubusercontent.com/u/6452323?v=4&s=100\" width=\"100px;\" alt=\"\"/>\n                    <br />\n                    Fernando Hurtado\n                </a>\n                <br />\n                (1st <a href=\"https://kysely.dev\">docs</a>)\n            </td>\n            <td align=\"center\">\n                <a href=\"https://github.com/wirekang\">\n                    <img src=\"https://avatars.githubusercontent.com/u/43294688?v=4&s=100\" width=\"100px;\" alt=\"\"/>\n                    <br />\n                    Wirekang\n                </a>\n                <br />\n                (<a href=\"https://kyse.link\">playground</a>)\n            </td>\n            <td align=\"center\">\n                <a href=\"https://github.com/tgriesser\">\n                    <img src=\"https://avatars.githubusercontent.com/u/154748?v=4&s=100\" width=\"100px;\" alt=\"\"/>\n                    <br />\n                    Tim Griesser\n                </a>\n                <br />\n                (<a href=\"https://knexjs.org/\">Knex</a>)\n            </td>\n        </tr>\n        <tr>\n            <td align=\"center\">\n                <a href=\"https://github.com/RobinBlomberg\">\n                    <img src=\"https://avatars.githubusercontent.com/u/20827397?v=4&s=100\" width=\"100px;\" alt=\"\"/>\n                    <br />\n                    Robin Blomberg\n                </a>\n                <br />\n                (<a href=\"https://github.com/RobinBlomberg/kysely-codegen\">codegen</a>)\n            </td>\n                        <td align=\"center\">\n                <a href=\"https://github.com/nexxeln\">\n                    <img src=\"https://avatars.githubusercontent.com/u/95541290?v=4&s=100\" width=\"100px\" alt=\"\" />\n                    <br />\n                    Shoubhit Dash\n                </a>\n                <br />\n                (prisma <a href=\"https://www.nexxel.dev/blog/typesafe-database\">idea</a>)\n            </td>\n            <td align=\"center\">\n                <a href=\"https://github.com/nexxeln\">\n                    <img src=\"https://avatars.githubusercontent.com/u/3050355?v=4&s=100\" width=\"100px\" alt=\"\" />\n                    <br />\n                    Valtýr Örn Kjartansson\n                </a>\n                <br />\n                (prisma <a href=\"https://github.com/valtyr/prisma-kysely\">impl</a>)\n            </td>\n        </tr>\n        <tr>\n            <td align=\"center\">\n                <a href=\"https://github.com/thdxr\">\n                    <img src=\"https://avatars.githubusercontent.com/u/826656?v=4&s=100\" width=\"100px;\" alt=\"\"/>\n                    <br />\n                    Dax Raad\n                </a>\n                <br />\n                (early <a href=\"https://thdxr.com/post/serverless-relational-showdown\">adopter</a>)\n            </td>\n            <td align=\"center\">\n                <a href=\"https://github.com/t3dotgg\">\n                    <img src=\"https://avatars.githubusercontent.com/u/6751787?v=4&s=100\" width=\"100px;\" alt=\"\"/>\n                    <br />\n                    Theo Browne\n                </a>\n                <br />\n                (early <a href=\"https://discord.com/channels/966627436387266600/988912020558602331/993220628154961930\">promoter</a>)\n            </td>\n            <td align=\"center\">\n                <a href=\"https://github.com/leerob\">\n                    <img src=\"https://avatars.githubusercontent.com/u/9113740?v=4&s=100\" width=\"100px;\" alt=\"\" />\n                    <br />\n                    Lee Robinson\n                </a>\n                <br />\n                (early <a href=\"https://x.com/leerob/status/1576929372811849730\">promoter</a>)\n            </td>\n        </tr>\n        <tr>\n            <td align=\"center\">\n                <a href=\"https://github.com/ethanresnick\">\n                    <img src=\"https://avatars.githubusercontent.com/u/471894?v=4&s=100\" width=\"100px\" alt=\"\" />\n                    <br />\n                    Ethan Resnick\n                </a>\n                <br />\n                (timely <a href=\"https://github.com/kysely-org/kysely/issues/494\">feedback</a>)\n            </td>\n            <td align=\"center\">\n                <a href=\"https://github.com/thetutlage\">\n                    <img src=\"https://avatars.githubusercontent.com/u/1706381?v=4&s=100\" width=\"100px;\" alt=\"\" />\n                    <br />\n                    Harminder Virk\n                </a>\n                <br />\n                (dope <a href=\"https://github.com/thetutlage/meta/discussions/8\">writeup</a>)\n            </td>\n            <td align=\"center\">\n                <a href=\"https://github.com/elitan\">\n                    <img src=\"https://avatars.githubusercontent.com/u/331818?v=4&s=100\" width=\"100px;\" alt=\"\" />\n                    <br />\n                    Johan Eliasson\n                </a>\n                <br />\n                (<a href=\"https://eliasson.me/articles/crafting-the-perfect-t3-stack-my-journey-with-kysely-atlas-and-clerk\">promoter</a>/<a href=\"https://www.youtube.com/watch?v=u2s39dRIpCM\">educator</a>)\n            </td>\n        </tr>\n        <!-- <tr>\n            <td align=\"center\">\n                <a href=\"\">\n                    <img src=\"\" width=\"100px;\" alt=\"\" />\n                    <br />\n                    Name\n                </a>\n                <br />\n                (contribution)\n            </td>\n        </tr> -->\n    </tbody>\n</table>\n\n## All contributors\n\n<p align=\"center\">\n    <a href=\"https://github.com/kysely-org/kysely/graphs/contributors\">\n        <img src=\"https://contrib.rocks/image?repo=kysely-org/kysely\" />\n    </a>\n    </br>\n    <span>Want to contribute? Check out our <a href=\"./CONTRIBUTING.md\" >contribution guidelines</a>.</span>\n</p>\n\n<p align=\"center\">\n    <a href=\"https://vercel.com/?utm_source=kysely&utm_campaign=oss\">\n        <img src=\"https://kysely.dev/img/powered-by-vercel.svg\" alt=\"Powered by Vercel\" />\n    </a>\n</p>\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\nWe take security seriously. We are responsible maintainers. Kysely is widely used in production and there's a lot at stake.\n\nWe're not perfect.\n\n## Supply Chain Attacks\n\nWe're on the frontline. We listen, we adapt. We try to use up-to-date best practices and standards from the maintainer community.\n\nBeing hacked and helping distribute malicious code to our community will be soul crushing to us.\n\nWe're not perfect. GitHub is not perfect. [NPM](https://npmjs.com) is not perfect.\n\n### Recommendations\n\nThese are not perfect.\n\n1. Our runtimes are not perfect. Keep yours up-to-date - [End Of Life (EOL) versions don't receive security updates](https://nodejs.org/en/blog/announcements/node-18-eol-support) and there are fewer eyes watching.\n\n1. [`pnpm`](https://pnpm.io) is not perfect, but it's the [closest](https://pnpm.io/supply-chain-security) we have - use it as your package manager.\n\n    1. It offers out the box [protection from malicious `postinstall` scripts](https://pnpm.io/settings#onlybuiltdependencies) - many attackers use `postinstall` scripts to run/setup their malicious code while you install the package.\n    1. It allows to [ignore new package versions](https://pnpm.io/settings#minimumreleaseage) with a configurable time period - response to supply chain attacks (regaining NPM/GitHub access, pulling the malicious package versions off NPM and publishing new safe versions) usually takes up to 24 hours.\n\n1. [Provenance](https://docs.npmjs.com/viewing-package-provenance) is not perfect, but it's the closest we have - audit publish flows, source commits, builds, etc.\n\n1. Our ecosystem is not perfect. Simplify/flatten your dependency graph. You probably don't need some of those libraries. Your runtime might have a native solution for some of these things. You can copy that single function over - attackers prey on (undermaintained) transitive dependencies as the blast radius is bigger, and response takes longer.\n\n1. Auth is not perfect. Use secret/password managers. Encrypt. [2FA](https://en.wikipedia.org/wiki/Multi-factor_authentication) everything. Don't access production directly from laptops - many attacks involve exfiltration, and they're [getting more creative](https://www.anthropic.com/news/detecting-countering-misuse-aug-2025).\n\n## Reporting Security Issues\n\nTo report a security issue, please use the GitHub Security Advisory [\"Report a Vulnerability\"](https://github.com/kysely-org/kysely/security/advisories/new) tab.\n\nDon't abuse the system. Don't waste our time with troll/spam/AI slop false reports.\n\nDon't be an asshole. We're not perfect.\n"
  },
  {
    "path": "deno.check.d.ts",
    "content": "import type {\n  ColumnType,\n  Generated,\n  GeneratedAlways,\n  Insertable,\n  Kysely,\n  Selectable,\n  SqlBool,\n  Updateable,\n} from './dist/esm'\n\nexport interface Database {\n  audit: AuditTable\n  person: PersonTable\n  person_backup: PersonTable\n  pet: PetTable\n  toy: ToyTable\n  wine: WineTable\n  wine_stock_change: WineStockChangeTable\n}\n\ninterface AuditTable {\n  id: Generated<number>\n  action: string\n}\n\ninterface PersonTable {\n  id: Generated<number>\n  address: { city: string } | null\n  age: number | null\n  birthdate: ColumnType<Date | null, string | null | undefined, string | null>\n  created_at: GeneratedAlways<Date>\n  deleted_at: ColumnType<Date | null, string | null | undefined, string | null>\n  experience: { role: string }[] | null\n  first_name: string\n  gender: 'male' | 'female' | 'other' | null\n  has_pets: Generated<'Y' | 'N'>\n  last_name: string | null\n  middle_name: string | null\n  nicknames: string[] | null\n  nullable_column: string | null\n  profile: {\n    addresses: { city: string }[]\n    website: { url: string }\n  } | null\n  updated_at: ColumnType<Date | null, string | null | undefined, string | null>\n  marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n}\n\ninterface PetTable {\n  id: Generated<number>\n  created_at: GeneratedAlways<Date>\n  is_favorite: Generated<SqlBool>\n  name: string\n  owner_id: number\n  species: Species\n}\n\ninterface ToyTable {\n  id: Generated<number>\n  name: string\n  pet_id: number\n  price: number\n}\n\ninterface WineTable {\n  id: Generated<number>\n  name: string\n  stock: number\n}\n\ninterface WineStockChangeTable {\n  id: Generated<number>\n  stock_delta: number\n  wine_name: string\n}\n\nexport type Person = Selectable<PersonTable>\nexport type NewPerson = Insertable<PersonTable>\nexport type PersonUpdate = Updateable<PersonTable>\nexport type Pet = Selectable<PetTable>\nexport type NewPet = Insertable<PetTable>\nexport type PetUpdate = Updateable<PetTable>\nexport type Species = 'dog' | 'cat' | 'hamster'\n\ndeclare global {\n  // @ts-ignore\n  export class Buffer {\n    static isBuffer(obj: unknown): obj is { length: number }\n    static compare(a: Buffer, b: Buffer): number\n  }\n  export const db: Kysely<Database>\n  export function functionThatExpectsPersonWithNonNullValue(\n    person: Person & { nullable_column: string },\n  ): void\n}\n"
  },
  {
    "path": "deno.check.json",
    "content": "{\n  \"$schema\": \"https://deno.land/x/deno/cli/schemas/config-file.v1.json\",\n  \"compilerOptions\": {\n    \"types\": [\"./deno.check.d.ts\"]\n  },\n  \"imports\": {\n    \"better-sqlite3\": \"npm:better-sqlite3\",\n    \"kysely\": \"./dist/esm\",\n    \"kysely/helpers/mssql\": \"./dist/esm/helpers/mssql.js\",\n    \"kysely/helpers/mysql\": \"./dist/esm/helpers/mysql.js\",\n    \"kysely/helpers/postgres\": \"./dist/esm/helpers/postgres.js\",\n    \"kysely/helpers/sqlite\": \"./dist/esm/helpers/sqlite.js\",\n    \"lodash/snakeCase\": \"npm:lodash/snakeCase\",\n    \"mysql2\": \"npm:mysql2\",\n    \"pg\": \"npm:pg\",\n    \"pg-cursor\": \"npm:pg-cursor\",\n    \"tarn\": \"npm:tarn\",\n    \"tedious\": \"npm:tedious\",\n    \"type-editor\": \"./deno.check.d.ts\"\n  }\n}\n"
  },
  {
    "path": "deno.lint.json",
    "content": "{\n  \"$schema\": \"https://deno.land/x/deno/cli/schemas/config-file.v1.json\",\n  \"lint\": {\n    \"rules\": {\n      \"tags\": [\"jsr\"]\n    }\n  }\n}\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "services:\n  # credit to Knex.js team for the following mssql setup here:\n  mssql:\n    image: mcr.microsoft.com/mssql/server:2022-latest\n    ports:\n      - '21433:1433'\n    environment:\n      ACCEPT_EULA: Y\n      MSSQL_PID: Express\n      SA_PASSWORD: KyselyTest0\n    healthcheck:\n      test: /opt/mssql-tools/bin/sqlcmd -S mssql -U sa -P 'KyselyTest0' -Q 'select 1'\n  waitmssql:\n    image: mcr.microsoft.com/mssql/server:2017-latest\n    links:\n      - mssql\n    depends_on:\n      - mssql\n    environment:\n      MSSQL_PID: Express\n    entrypoint:\n      - bash\n      - -c\n      # https://docs.microsoft.com/en-us/sql/relational-databases/logs/control-transaction-durability?view=sql-server-ver15#bkmk_DbControl\n      - 'until /opt/mssql-tools/bin/sqlcmd -S mssql -U sa -P KyselyTest0 -d master -Q \"CREATE DATABASE kysely_test; ALTER DATABASE kysely_test SET ALLOW_SNAPSHOT_ISOLATION ON; ALTER DATABASE kysely_test SET DELAYED_DURABILITY = FORCED\"; do sleep 5; done'\n  mysql:\n    image: 'mysql/mysql-server'\n    environment:\n      MYSQL_ROOT_PASSWORD: root\n      MYSQL_DATABASE: kysely_test\n    ports:\n      - '3308:3306'\n    volumes:\n      - ./test/scripts/mysql-init.sql:/data/application/init.sql\n    command: --init-file /data/application/init.sql\n  postgres:\n    image: 'postgres'\n    environment:\n      POSTGRES_DB: kysely_test\n      POSTGRES_USER: kysely\n      POSTGRES_HOST_AUTH_METHOD: trust\n    ports:\n      - '5434:5432'\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta\n      http-equiv=\"refresh\"\n      content=\"0; url='https://kysely-org.github.io/kysely-apidoc'\"\n    />\n  </head>\n  <body></body>\n</html>\n"
  },
  {
    "path": "example/.gitignore",
    "content": "lib\nnode_modules\n.vscode\n"
  },
  {
    "path": "example/.prettierrc.json",
    "content": "{\n  \"semi\": false,\n  \"singleQuote\": true\n}\n"
  },
  {
    "path": "example/README.md",
    "content": "# An example server that uses Kysely\n\nThis is a simple but realistic Koa based server that shows one way to use Kysely. Since this example attempts to mimic a real world project, most of the code isn't relevant to learning how to use Kysely. The relevant parts are the repositories and how they are used. This examples is by no means the best or the right way to use Kysely, but simply one possible way.\n\nThe server has three main levels of abstraction:\n\n1. **Repository**: Repositories contain all Kysely code and provide higher level methods for dealing with the database.\n\n2. **Service**: All business logic is implemented in the service layer. Services use repositories to interact with the database. While repositories deal with database rows and types like `UserRow` the service layer doesn't leak out those types. For example user service methods return and take `User` objects instead of `UserRow` objects.\n\n3. **Controller**: Controllers define the HTTP API. Controllers validate and convert the inputs and outputs from/to the network and call services to carry out the actual business logic.\n\n## Running the example\n\nAll you need to do start poking around with the code is to clone kysely, go to the example folder and run:\n\n```\nnpm install\nnpm test\n```\n\nYou need to have postgres running in the default port `5432` and the default postgres user `postgres` should exist with no password. You can modify the [test configuration](https://github.com/kysely-org/kysely/blob/master/example/test/test-config.ts) if you want to use different settings.\n"
  },
  {
    "path": "example/package.json",
    "content": "{\n  \"name\": \"kysely_koa_example\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"build\": \"rm -rf dist && tsc\",\n    \"test\": \"mocha --timeout 5000 -r ts-node/register test/**/*.test.ts\",\n    \"migrate:latest\": \"node dist/migrate-to-latest.js\"\n  },\n  \"author\": \"Sami Koskimäki <sami@jakso.me>\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"ajv\": \"^8.11.2\",\n    \"dotenv\": \"^16.0.0\",\n    \"jsonwebtoken\": \"^9.0.0\",\n    \"koa\": \"^2.14.1\",\n    \"koa-bodyparser\": \"^4.3.0\",\n    \"koa-compress\": \"^5.1.0\",\n    \"koa-json\": \"^2.0.2\",\n    \"koa-router\": \"^12.0.0\",\n    \"kysely\": \"0.23.3\",\n    \"pg\": \"^8.8.0\"\n  },\n  \"devDependencies\": {\n    \"@types/chai\": \"^4.3.4\",\n    \"@types/jsonwebtoken\": \"^9.0.0\",\n    \"@types/koa\": \"^2.13.5\",\n    \"@types/koa-bodyparser\": \"^4.3.10\",\n    \"@types/koa-compress\": \"^4.0.3\",\n    \"@types/koa-json\": \"^2.0.20\",\n    \"@types/koa-router\": \"^7.4.4\",\n    \"@types/mocha\": \"^10.0.1\",\n    \"@types/node\": \"^16.11.9\",\n    \"axios\": \"^1.2.2\",\n    \"chai\": \"^4.3.7\",\n    \"mocha\": \"^10.2.0\",\n    \"ts-node\": \"^10.9.1\",\n    \"typescript\": \"^4.9.4\"\n  }\n}\n"
  },
  {
    "path": "example/src/app.ts",
    "content": "import * as Koa from 'koa'\nimport * as json from 'koa-json'\nimport * as compress from 'koa-compress'\nimport * as bodyParser from 'koa-bodyparser'\nimport { Server } from 'http'\nimport { Kysely, PostgresDialect } from 'kysely'\n\nimport { Config } from './config'\nimport { Context, ContextExtension } from './context'\nimport { Database } from './database'\nimport { Router } from './router'\nimport { userController } from './user/user.controller'\nimport { ControllerError } from './util/errors'\nimport { isObject } from './util/object'\nimport { Pool } from 'pg'\n\nexport class App {\n  #config: Config\n  #koa: Koa<any, ContextExtension>\n  #router: Router\n  #db: Kysely<Database>\n  #server?: Server\n\n  constructor(config: Config) {\n    this.#config = config\n    this.#koa = new Koa()\n    this.#router = new Router()\n    this.#db = new Kysely<Database>({\n      dialect: new PostgresDialect({\n        pool: async () => new Pool(this.#config.database),\n      }),\n    })\n\n    this.#koa.use(compress())\n    this.#koa.use(bodyParser())\n    this.#koa.use(json())\n\n    this.#koa.use(this.errorHandler)\n    this.#koa.use(this.decorateContext)\n\n    userController(this.#router)\n\n    this.#koa.use(this.#router.routes())\n    this.#koa.use(this.#router.allowedMethods())\n  }\n\n  get db(): Kysely<Database> {\n    return this.#db\n  }\n\n  async start(): Promise<void> {\n    return new Promise((resolve) => {\n      this.#server = this.#koa.listen(this.#config.port, resolve)\n    })\n  }\n\n  async stop(): Promise<void> {\n    await new Promise<void>((resolve, reject) => {\n      this.#server?.close((err) => {\n        if (err) {\n          reject(err)\n        } else {\n          resolve()\n        }\n      })\n    })\n\n    await this.#db?.destroy()\n  }\n\n  private readonly errorHandler = async (\n    ctx: Context,\n    next: Koa.Next,\n  ): Promise<void> => {\n    try {\n      await next()\n    } catch (error) {\n      if (error instanceof ControllerError) {\n        respondError(ctx, error)\n      } else {\n        respondError(ctx, createUnknownError(error))\n      }\n    }\n  }\n\n  private readonly decorateContext = async (\n    ctx: Context,\n    next: Koa.Next,\n  ): Promise<void> => {\n    ctx.db = this.#db!\n    await next()\n  }\n}\n\nfunction respondError(ctx: Context, error: ControllerError): void {\n  ctx.status = error.status\n  ctx.body = error.toJSON()\n}\n\nfunction createUnknownError(error: unknown): ControllerError {\n  return new ControllerError(\n    500,\n    'UnknownError',\n    (isObject(error) ? error.message : undefined) ?? 'unknown error',\n  )\n}\n"
  },
  {
    "path": "example/src/authentication/auth-token.service.ts",
    "content": "import * as jwt from 'jsonwebtoken'\nimport * as refreshTokenRepository from './refresh-token.repository'\nimport { Kysely } from 'kysely'\nimport { config } from '../config'\nimport { Database } from '../database'\nimport { AuthToken } from './auth-token'\nimport { RefreshToken } from './refresh-token'\n\nexport class AuthTokenError extends Error {}\nexport class InvalidAuthTokenError extends AuthTokenError {}\nexport class AuthTokenExpiredError extends AuthTokenError {}\nexport class RefreshTokenUserIdMismatchError extends Error {}\n\nexport interface AuthTokenPayload {\n  userId: string\n  refreshTokenId: string\n}\n\ninterface RefreshTokenPayload {\n  userId: string\n  refreshTokenId: string\n  isRefreshToken: true\n}\n\nexport async function createRefreshToken(\n  db: Kysely<Database>,\n  userId: string,\n): Promise<RefreshToken> {\n  const { refresh_token_id } = await refreshTokenRepository.insertRefreshToken(\n    db,\n    userId,\n  )\n\n  return signRefreshToken({\n    userId,\n    refreshTokenId: refresh_token_id,\n    isRefreshToken: true,\n  })\n}\n\nfunction signRefreshToken(tokenPayload: RefreshTokenPayload): RefreshToken {\n  // Refresh tokens never expire.\n  return { refreshToken: jwt.sign(tokenPayload, config.authTokenSecret) }\n}\n\nexport async function createAuthToken(\n  db: Kysely<Database>,\n  refreshToken: RefreshToken,\n): Promise<AuthToken> {\n  const { userId, refreshTokenId } = verifyRefreshToken(refreshToken)\n\n  await refreshTokenRepository.updateRefreshToken(db, refreshTokenId, {\n    last_refreshed_at: new Date(),\n  })\n\n  return signAuthToken({ userId, refreshTokenId })\n}\n\nfunction verifyRefreshToken(token: RefreshToken): RefreshTokenPayload {\n  const payload = verifyToken(token.refreshToken)\n\n  if (\n    !payload ||\n    typeof payload !== 'object' ||\n    typeof payload.userId !== 'string' ||\n    typeof payload.refreshTokenId !== 'string' ||\n    payload.isRefreshToken !== true\n  ) {\n    throw new InvalidAuthTokenError()\n  }\n\n  return {\n    userId: payload.userId,\n    refreshTokenId: payload.refreshTokenId,\n    isRefreshToken: true,\n  }\n}\n\nfunction signAuthToken(tokenPayload: AuthTokenPayload): AuthToken {\n  return {\n    authToken: jwt.sign(tokenPayload, config.authTokenSecret, {\n      expiresIn: config.authTokenExpiryDuration,\n    }),\n  }\n}\n\nexport function verifyAuthToken(token: AuthToken): AuthTokenPayload {\n  const payload = verifyToken(token.authToken)\n\n  if (\n    !payload ||\n    typeof payload !== 'object' ||\n    typeof payload.userId !== 'string' ||\n    typeof payload.refreshTokenId !== 'string'\n  ) {\n    throw new InvalidAuthTokenError()\n  }\n\n  return {\n    userId: payload.userId,\n    refreshTokenId: payload.refreshTokenId,\n  }\n}\n\nfunction verifyToken(token: string): string | jwt.JwtPayload {\n  try {\n    return jwt.verify(token, config.authTokenSecret)\n  } catch (error) {\n    if (error instanceof jwt.TokenExpiredError) {\n      throw new AuthTokenExpiredError()\n    }\n\n    throw new InvalidAuthTokenError()\n  }\n}\n\nexport async function deleteRefreshToken(\n  db: Kysely<Database>,\n  userId: string,\n  refreshToken: RefreshToken,\n): Promise<void> {\n  const payload = verifyRefreshToken(refreshToken)\n\n  if (payload.userId !== userId) {\n    throw new RefreshTokenUserIdMismatchError()\n  }\n\n  await db\n    .deleteFrom('refresh_token')\n    .where('refresh_token_id', '=', payload.refreshTokenId)\n    .execute()\n}\n"
  },
  {
    "path": "example/src/authentication/auth-token.ts",
    "content": "export interface AuthToken {\n  authToken: string\n}\n"
  },
  {
    "path": "example/src/authentication/authentication.service.ts",
    "content": "import * as refreshTokenRepository from './refresh-token.repository'\nimport * as authTokenService from './auth-token.service'\n\nimport { AuthTokenExpiredError, AuthTokenPayload } from './auth-token.service'\nimport { Next } from 'koa'\nimport { Context } from '../context'\nimport { ControllerError } from '../util/errors'\n\nexport async function authenticateUser(\n  ctx: Context,\n  next: Next,\n): Promise<void> {\n  const { userId } = ctx.params\n\n  if (!userId) {\n    throw new ControllerError(\n      400,\n      'NoUserIdParameter',\n      'no user id parameter found in the route',\n    )\n  }\n\n  const authorization = ctx.headers['authorization']\n\n  if (!authorization || !authorization.startsWith('Bearer ')) {\n    throw new ControllerError(\n      400,\n      'InvalidAuthorizationHeader',\n      'missing or invalid Authorization header',\n    )\n  }\n\n  const authToken = authorization.substring('Bearer '.length)\n  let authTokenPayload: AuthTokenPayload | undefined\n\n  try {\n    authTokenPayload = authTokenService.verifyAuthToken({ authToken })\n  } catch (error) {\n    if (error instanceof AuthTokenExpiredError) {\n      throw new ControllerError(\n        401,\n        'ExpiredAuthToken',\n        'the auth token has expired',\n      )\n    }\n\n    throw new ControllerError(401, 'InvalidAuthToken', 'invalid auth token')\n  }\n\n  if (userId !== authTokenPayload.userId) {\n    throw new ControllerError(403, 'UserMismatch', \"wrong user's auth token\")\n  }\n\n  const refreshToken = await refreshTokenRepository.findRefreshToken(\n    ctx.db,\n    authTokenPayload.userId,\n    authTokenPayload.refreshTokenId,\n  )\n\n  if (!refreshToken) {\n    throw new ControllerError(\n      404,\n      'UserOrRefreshTokenNotFound',\n      'either the user or the refresh token has been deleted',\n    )\n  }\n\n  return next()\n}\n"
  },
  {
    "path": "example/src/authentication/refresh-token.repository.ts",
    "content": "import { Kysely } from 'kysely'\nimport { Database } from '../database'\nimport {\n  RefreshTokenRow,\n  UpdateableRefreshTokenRow,\n} from './refresh-token.table'\n\nexport async function insertRefreshToken(\n  db: Kysely<Database>,\n  userId: string,\n): Promise<RefreshTokenRow> {\n  const [refreshToken] = await db\n    .insertInto('refresh_token')\n    .values({\n      user_id: userId,\n      last_refreshed_at: new Date(),\n    })\n    .returningAll()\n    .execute()\n\n  return refreshToken\n}\n\nexport async function findRefreshToken(\n  db: Kysely<Database>,\n  userId: string,\n  refreshTokenId: string,\n): Promise<RefreshTokenRow | undefined> {\n  const token = await db\n    .selectFrom('refresh_token as rt')\n    .selectAll('rt')\n    .innerJoin('user as u', 'rt.user_id', 'u.user_id')\n    .where('u.user_id', '=', userId)\n    .where('rt.refresh_token_id', '=', refreshTokenId)\n    .executeTakeFirst()\n\n  return token\n}\n\nexport async function updateRefreshToken(\n  db: Kysely<Database>,\n  refreshTokenId: string,\n  patch: Pick<UpdateableRefreshTokenRow, 'last_refreshed_at'>,\n): Promise<void> {\n  await db\n    .updateTable('refresh_token')\n    .set(patch)\n    .where('refresh_token_id', '=', refreshTokenId)\n    .execute()\n}\n"
  },
  {
    "path": "example/src/authentication/refresh-token.table.ts",
    "content": "import { Generated, Insertable, Selectable, Updateable } from 'kysely'\n\nexport interface RefreshTokenTable {\n  refresh_token_id: Generated<string>\n  user_id: string\n  last_refreshed_at: Date\n  created_at: Generated<Date>\n}\n\nexport type RefreshTokenRow = Selectable<RefreshTokenTable>\nexport type InsertableRefreshTokenRow = Insertable<RefreshTokenTable>\nexport type UpdateableRefreshTokenRow = Updateable<RefreshTokenTable>\n"
  },
  {
    "path": "example/src/authentication/refresh-token.ts",
    "content": "import { ajv } from '../util/ajv'\n\nexport interface RefreshToken {\n  refreshToken: string\n}\n\nexport const validateRefreshToken = ajv.compile<RefreshToken>({\n  type: 'object',\n  required: ['refreshToken'],\n  properties: {\n    refreshToken: {\n      type: 'string',\n    },\n  },\n})\n"
  },
  {
    "path": "example/src/config.ts",
    "content": "import * as dotenv from 'dotenv'\nimport { ConnectionConfig } from 'pg'\n\ndotenv.config()\n\nexport interface Config {\n  readonly port: number\n  readonly authTokenSecret: string\n  readonly authTokenExpiryDuration: string\n  readonly database: ConnectionConfig\n}\n\nexport const config: Config = Object.freeze({\n  port: parseInt(getEnvVariable('PORT'), 10),\n  authTokenSecret: getEnvVariable('AUTH_TOKEN_SECRET'),\n  authTokenExpiryDuration: getEnvVariable('AUTH_TOKEN_EXIRY_DURATION'),\n  database: Object.freeze({\n    database: getEnvVariable('DATABASE'),\n    host: getEnvVariable('DATABASE_HOST'),\n    user: getEnvVariable('DATABASE_USER'),\n  }),\n})\n\nfunction getEnvVariable(name: string): string {\n  if (!process.env[name]) {\n    throw new Error(`environment variable ${name} not found`)\n  }\n\n  return process.env[name]!\n}\n"
  },
  {
    "path": "example/src/context.ts",
    "content": "import * as Koa from 'koa'\nimport * as KoaRouter from 'koa-router'\n\nimport { Kysely } from 'kysely'\nimport { Database } from './database'\n\nexport interface ContextExtension {\n  db: Kysely<Database>\n}\n\nexport type Context = Koa.ParameterizedContext<\n  any,\n  ContextExtension & KoaRouter.IRouterParamContext<any, ContextExtension>,\n  any\n>\n"
  },
  {
    "path": "example/src/database.ts",
    "content": "import { RefreshTokenTable } from './authentication/refresh-token.table'\nimport { PasswordSignInMethodTable } from './user/sign-in-method/password-sign-in-method.table'\nimport { SignInMethodTable } from './user/sign-in-method/sign-in-method.table'\nimport { UserTable } from './user/user.table'\n\nexport interface Database {\n  user: UserTable\n  refresh_token: RefreshTokenTable\n  sign_in_method: SignInMethodTable\n  password_sign_in_method: PasswordSignInMethodTable\n}\n"
  },
  {
    "path": "example/src/migrate-to-latest.ts",
    "content": "import * as path from 'path'\nimport { promises as fs } from 'fs'\nimport { Database } from './database'\nimport { config } from './config'\nimport {\n  Kysely,\n  Migrator,\n  PostgresDialect,\n  FileMigrationProvider,\n} from 'kysely'\nimport { Pool } from 'pg'\n\nasync function migrateToLatest() {\n  const db = new Kysely<Database>({\n    dialect: new PostgresDialect({\n      pool: new Pool(config.database),\n    }),\n  })\n\n  const migrator = new Migrator({\n    db,\n    provider: new FileMigrationProvider({\n      fs,\n      path,\n      migrationFolder: path.join(__dirname, 'migrations'),\n    }),\n  })\n\n  const { error, results } = await migrator.migrateToLatest()\n\n  results?.forEach((it) => {\n    if (it.status === 'Success') {\n      console.log(`migration \"${it.migrationName}\" was executed successfully`)\n    } else if (it.status === 'Error') {\n      console.error(`failed to execute migration \"${it.migrationName}\"`)\n    }\n  })\n\n  if (error) {\n    console.error('failed to migrate')\n    console.error(error)\n    process.exit(1)\n  }\n\n  await db.destroy()\n}\n\nmigrateToLatest()\n"
  },
  {
    "path": "example/src/migrations/2021_09_18_06_54_59_create_user.ts",
    "content": "import { Kysely, sql } from 'kysely'\n\nexport async function up(db: Kysely<any>): Promise<void> {\n  await db.schema\n    .createTable('user')\n    .addColumn('user_id', 'uuid', (col) =>\n      col.primaryKey().defaultTo(sql`gen_random_uuid()`),\n    )\n    .addColumn('first_name', 'text')\n    .addColumn('last_name', 'text')\n    .addColumn('email', 'text', (col) => col.unique())\n    .addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql`NOW()`))\n    .execute()\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n  await db.schema.dropTable('user').execute()\n}\n"
  },
  {
    "path": "example/src/migrations/2021_09_18_14_05_20_create_refresh_token.ts",
    "content": "import { Kysely, sql } from 'kysely'\n\nexport async function up(db: Kysely<any>): Promise<void> {\n  await db.schema\n    .createTable('refresh_token')\n    .addColumn('refresh_token_id', 'uuid', (col) =>\n      col.primaryKey().defaultTo(sql`gen_random_uuid()`),\n    )\n    .addColumn('user_id', 'uuid', (col) =>\n      col.references('user.user_id').notNull().onDelete('cascade'),\n    )\n    .addColumn('last_refreshed_at', 'timestamp', (col) => col.notNull())\n    .addColumn('created_at', 'timestamp', (col) =>\n      col.notNull().defaultTo(sql`NOW()`),\n    )\n    .execute()\n\n  await db.schema\n    .createIndex('refresh_token_user_id_index')\n    .on('refresh_token')\n    .column('user_id')\n    .execute()\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n  await db.schema.dropTable('refresh_token').execute()\n}\n"
  },
  {
    "path": "example/src/migrations/2021_09_18_18_22_45_create_sign_in_method.ts",
    "content": "import { Kysely } from 'kysely'\n\nexport async function up(db: Kysely<any>): Promise<void> {\n  await db.schema\n    .createTable('sign_in_method')\n    .addColumn('user_id', 'uuid', (col) =>\n      col.references('user.user_id').notNull().onDelete('cascade'),\n    )\n    .addColumn('type', 'text', (col) => col.notNull())\n    .addPrimaryKeyConstraint('sign_in_method_primary_key', ['user_id', 'type'])\n    .execute()\n\n  await db.schema\n    .createTable('password_sign_in_method')\n    .addColumn('user_id', 'uuid', (col) =>\n      col.references('user.user_id').notNull().primaryKey().onDelete('cascade'),\n    )\n    .addColumn('password_hash', 'text', (col) => col.notNull())\n    .execute()\n\n  await db.schema\n    .createIndex('sign_in_method_user_id_index')\n    .on('sign_in_method')\n    .column('user_id')\n    .execute()\n\n  await db.schema\n    .createIndex('password_sign_in_method_user_id_index')\n    .on('password_sign_in_method')\n    .column('user_id')\n    .execute()\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n  await db.schema.dropTable('sign_in_method').execute()\n  await db.schema.dropTable('password_sign_in_method').execute()\n}\n"
  },
  {
    "path": "example/src/router.ts",
    "content": "import * as KoaRouter from 'koa-router'\n\nimport { ContextExtension } from './context'\n\nexport class Router extends KoaRouter<any, ContextExtension> {}\n"
  },
  {
    "path": "example/src/user/sign-in-method/password-sign-in-method.table.ts",
    "content": "import { Insertable, Selectable, Updateable } from 'kysely'\n\nexport interface PasswordSignInMethodTable {\n  user_id: string\n  password_hash: string\n}\n\nexport type PasswordSignInMethodRow = Selectable<PasswordSignInMethodTable>\n\nexport type InsertablePasswordSignInMethodRow =\n  Insertable<PasswordSignInMethodTable>\n\nexport type UpdateablePasswordSignInMethodRow =\n  Updateable<PasswordSignInMethodTable>\n"
  },
  {
    "path": "example/src/user/sign-in-method/sign-in-method.controller.ts",
    "content": "import * as signInMethodService from './sign-in-method.service'\nimport * as authenticationService from '../../authentication/authentication.service'\nimport * as authTokenService from '../../authentication/auth-token.service'\n\nimport { RefreshTokenUserIdMismatchError } from '../../authentication/auth-token.service'\nimport {\n  PasswordTooLongError,\n  PasswordTooWeakError,\n  SignInMethodNotFoundError,\n  UserAlreadyHasSignInMethodError,\n  WrongPasswordError,\n} from './sign-in-method.service'\nimport { validateRefreshToken } from '../../authentication/refresh-token'\nimport { Router } from '../../router'\nimport { ControllerError, UserNotFoundError } from '../../util/errors'\nimport { validatePasswordSignInMethod } from './sign-in-method'\n\nexport function signInMethodController(router: Router): void {\n  router.post(\n    '/api/v1/user/:userId/sign-in-methods',\n    authenticationService.authenticateUser,\n    async (ctx) => {\n      const { body } = ctx.request\n\n      if (!validatePasswordSignInMethod(body)) {\n        throw new ControllerError(\n          400,\n          'InvalidSignInMethod',\n          'invalid sign in method',\n        )\n      }\n\n      try {\n        await ctx.db.transaction().execute(async (trx) => {\n          await signInMethodService.addPasswordSignInMethod(\n            trx,\n            ctx.params.userId,\n            body,\n          )\n        })\n\n        ctx.status = 201\n        ctx.body = { success: true }\n      } catch (error) {\n        if (error instanceof UserNotFoundError) {\n          throw new ControllerError(404, 'UserNotFound', 'user not found')\n        } else if (error instanceof PasswordTooWeakError) {\n          throw new ControllerError(\n            400,\n            'PasswordTooWeak',\n            'password is too weak',\n          )\n        } else if (error instanceof PasswordTooLongError) {\n          throw new ControllerError(\n            400,\n            'PasswordTooLong',\n            'password is too long',\n          )\n        } else if (error instanceof UserAlreadyHasSignInMethodError) {\n          throw new ControllerError(\n            409,\n            'UserAlreadyHasSignInMethod',\n            'the user already has a sign in method',\n          )\n        }\n\n        throw error\n      }\n    },\n  )\n\n  router.post('/api/v1/user/sign-in', async (ctx) => {\n    const { body } = ctx.request\n\n    if (!validatePasswordSignInMethod(body)) {\n      throw new ControllerError(\n        400,\n        'InvalidSignInMethod',\n        'invalid sign in method',\n      )\n    }\n\n    try {\n      const signedInUser = await ctx.db.transaction().execute(async (trx) => {\n        return signInMethodService.singInUsingPassword(trx, body)\n      })\n\n      ctx.status = 200\n      ctx.body = {\n        user: signedInUser.user,\n        authToken: signedInUser.authToken.authToken,\n        refreshToken: signedInUser.refreshToken.refreshToken,\n      }\n    } catch (error) {\n      if (\n        error instanceof UserNotFoundError ||\n        error instanceof WrongPasswordError ||\n        error instanceof SignInMethodNotFoundError\n      ) {\n        // Don't leak too much information about why the sign in failed.\n        throw new ControllerError(\n          401,\n          'InvalidCredentials',\n          'wrong email or password',\n        )\n      }\n\n      throw error\n    }\n  })\n\n  router.post(\n    '/api/v1/user/:userId/sign-out',\n    authenticationService.authenticateUser,\n    async (ctx) => {\n      const { body } = ctx.request\n\n      if (!validateRefreshToken(body)) {\n        throw new ControllerError(\n          400,\n          'InvalidRefreshToken',\n          'the body must contain a valid refresh token',\n        )\n      }\n\n      try {\n        await authTokenService.deleteRefreshToken(\n          ctx.db,\n          ctx.params.userId,\n          body,\n        )\n\n        ctx.status = 200\n        ctx.body = { success: true }\n      } catch (error) {\n        if (error instanceof RefreshTokenUserIdMismatchError) {\n          throw new ControllerError(\n            403,\n            'RefreshTokenUserIdMismatch',\n            \"cannot delete another user's refresh token\",\n          )\n        }\n\n        throw error\n      }\n    },\n  )\n}\n"
  },
  {
    "path": "example/src/user/sign-in-method/sign-in-method.repository.ts",
    "content": "import { Kysely } from 'kysely'\nimport { Database } from '../../database'\nimport {\n  InsertablePasswordSignInMethodRow,\n  PasswordSignInMethodRow,\n} from './password-sign-in-method.table'\n\nexport async function findPasswordSignInMethod(\n  db: Kysely<Database>,\n  userId: string,\n): Promise<PasswordSignInMethodRow | undefined> {\n  const method = await db\n    .selectFrom('sign_in_method as sim')\n    .innerJoin('password_sign_in_method as psim', 'psim.user_id', 'sim.user_id')\n    .selectAll('psim')\n    .where('sim.type', '=', 'password')\n    .where('sim.user_id', '=', userId)\n    .executeTakeFirst()\n\n  return method\n}\n\nexport async function insertPasswordSignInMethod(\n  db: Kysely<Database>,\n  method: InsertablePasswordSignInMethodRow,\n): Promise<PasswordSignInMethodRow> {\n  await db\n    .with('sim', (db) =>\n      db\n        .insertInto('sign_in_method')\n        .values({ user_id: method.user_id, type: 'password' }),\n    )\n    .insertInto('password_sign_in_method')\n    .values(method)\n    .execute()\n\n  return method\n}\n"
  },
  {
    "path": "example/src/user/sign-in-method/sign-in-method.service.ts",
    "content": "import * as crypto from 'crypto'\nimport * as signInMethodRepository from './sign-in-method.repository'\nimport * as userService from '../user.service'\nimport * as authTokenService from '../../authentication/auth-token.service'\n\nimport { Transaction } from 'kysely'\nimport { Database } from '../../database'\nimport { UserNotFoundError } from '../../util/errors'\nimport { SignedInUser } from '../signed-in-user'\nimport { PasswordSignInMethod } from './sign-in-method'\n\nexport const MIN_PASSWORD_LENGTH = 8\nexport const MAX_PASSWORD_LENGTH = 255\n\nexport class UserAlreadyHasSignInMethodError extends Error {}\nexport class SignInMethodNotFoundError extends Error {}\nexport class WrongPasswordError extends Error {}\nexport class PasswordTooWeakError extends Error {}\nexport class PasswordTooLongError extends Error {}\n\nexport async function addPasswordSignInMethod(\n  trx: Transaction<Database>,\n  userId: string,\n  method: PasswordSignInMethod,\n): Promise<void> {\n  const user = await userService.lockUserById(trx, userId)\n\n  if (!user) {\n    throw new UserNotFoundError()\n  }\n\n  if (user.email) {\n    throw new UserAlreadyHasSignInMethodError()\n  }\n\n  await signInMethodRepository.insertPasswordSignInMethod(trx, {\n    user_id: userId,\n    password_hash: await encryptPassword(method.password),\n  })\n\n  await userService.setUserEmail(trx, userId, method.email)\n}\n\nasync function encryptPassword(password: string): Promise<string> {\n  if (password.length < MIN_PASSWORD_LENGTH) {\n    throw new PasswordTooWeakError()\n  }\n\n  if (password.length > MAX_PASSWORD_LENGTH) {\n    throw new PasswordTooLongError()\n  }\n\n  return encryptSecret(password)\n}\n\nasync function encryptSecret(secret: string): Promise<string> {\n  const salt = crypto.randomBytes(16).toString('hex')\n  return `${salt}:${await scrypt(secret, salt)}`\n}\n\nasync function verifySecret(secret: string, hash: string): Promise<boolean> {\n  const [salt, secretHash] = hash.split(':')\n  return (await scrypt(secret, salt)) === secretHash\n}\n\nasync function scrypt(secret: string, salt: string): Promise<string> {\n  return new Promise((resolve, reject) => {\n    crypto.scrypt(\n      secret,\n      salt,\n      64,\n      { N: 16384, r: 8, p: 1 },\n      (err, secretHash) => {\n        if (err) {\n          return reject(err)\n        }\n\n        resolve(secretHash.toString('hex'))\n      },\n    )\n  })\n}\n\nexport async function singInUsingPassword(\n  trx: Transaction<Database>,\n  method: PasswordSignInMethod,\n): Promise<SignedInUser> {\n  const user = await userService.lockUserByEmail(trx, method.email)\n\n  if (!user) {\n    throw new UserNotFoundError()\n  }\n\n  const signInMethod = await signInMethodRepository.findPasswordSignInMethod(\n    trx,\n    user.id,\n  )\n\n  if (!signInMethod) {\n    throw new SignInMethodNotFoundError()\n  }\n\n  if (!(await verifyPassword(method.password, signInMethod.password_hash))) {\n    throw new WrongPasswordError()\n  }\n\n  const refreshToken = await authTokenService.createRefreshToken(trx, user.id)\n  const authToken = await authTokenService.createAuthToken(trx, refreshToken)\n\n  return {\n    user,\n    authToken,\n    refreshToken,\n  }\n}\n\nasync function verifyPassword(\n  password: string,\n  hash: string,\n): Promise<boolean> {\n  return verifySecret(password, hash)\n}\n"
  },
  {
    "path": "example/src/user/sign-in-method/sign-in-method.table.ts",
    "content": "import { Insertable, Selectable, Updateable } from 'kysely'\n\nexport interface SignInMethodTable {\n  user_id: string\n  type: 'password'\n}\n\nexport type SignInMethodRow = Selectable<SignInMethodTable>\nexport type InsertableSignInMethodRow = Insertable<SignInMethodTable>\nexport type UpdateableSignInMethodRow = Updateable<SignInMethodTable>\n"
  },
  {
    "path": "example/src/user/sign-in-method/sign-in-method.ts",
    "content": "import { ajv } from '../../util/ajv'\n\nexport type SignInMethod = PasswordSignInMethod\n\nexport interface PasswordSignInMethod {\n  email: string\n  password: string\n}\n\nexport const validatePasswordSignInMethod = ajv.compile<PasswordSignInMethod>({\n  type: 'object',\n  required: ['email', 'password'],\n  properties: {\n    email: {\n      type: 'string',\n    },\n    password: {\n      type: 'string',\n    },\n  },\n})\n"
  },
  {
    "path": "example/src/user/signed-in-user.ts",
    "content": "import { AuthToken } from '../authentication/auth-token'\nimport { RefreshToken } from '../authentication/refresh-token'\nimport { User } from './user'\n\nexport interface SignedInUser {\n  refreshToken: RefreshToken\n  authToken: AuthToken\n  user: User\n}\n"
  },
  {
    "path": "example/src/user/user.controller.ts",
    "content": "import * as userService from './user.service'\nimport * as authenticationService from '../authentication/authentication.service'\n\nimport { Router } from '../router'\nimport { signInMethodController } from './sign-in-method/sign-in-method.controller'\nimport { validateCreateAnonymousUserRequest } from './user'\nimport { ControllerError } from '../util/errors'\n\nexport function userController(router: Router): void {\n  router.post('/api/v1/user', async (ctx) => {\n    const { body } = ctx.request\n\n    if (!validateCreateAnonymousUserRequest(body)) {\n      throw new ControllerError(400, 'InvalidUser', 'invalid user')\n    }\n\n    const result = await ctx.db.transaction().execute(async (trx) => {\n      return userService.createAnonymousUser(trx, body)\n    })\n\n    ctx.status = 201\n    ctx.body = {\n      user: result.user,\n      authToken: result.authToken.authToken,\n      refreshToken: result.refreshToken.refreshToken,\n    }\n  })\n\n  router.get(\n    '/api/v1/user/:userId',\n    authenticationService.authenticateUser,\n    async (ctx) => {\n      const { userId } = ctx.params\n      const user = await userService.findUserById(ctx.db, userId)\n\n      if (!user) {\n        throw new ControllerError(\n          404,\n          'UserNotFound',\n          `user with id ${userId} was not found`,\n        )\n      }\n\n      ctx.body = { user }\n    },\n  )\n\n  signInMethodController(router)\n}\n"
  },
  {
    "path": "example/src/user/user.repository.ts",
    "content": "import { Kysely, Transaction } from 'kysely'\nimport { Database } from '../database'\nimport { InsertableUserRow, UserRow } from './user.table'\n\nexport async function insertUser(\n  db: Kysely<Database>,\n  user: InsertableUserRow,\n): Promise<UserRow> {\n  const insertedUser = await db\n    .insertInto('user')\n    .values(user)\n    .returningAll()\n    .executeTakeFirstOrThrow()\n\n  return insertedUser\n}\n\nexport async function findUserById(\n  db: Kysely<Database>,\n  id: string,\n): Promise<UserRow | undefined> {\n  const user = await db\n    .selectFrom('user')\n    .where('user_id', '=', id)\n    .selectAll('user')\n    .executeTakeFirst()\n\n  return user\n}\n\nexport async function lockUserById(\n  trx: Transaction<Database>,\n  id: string,\n): Promise<UserRow | undefined> {\n  return lockUser(trx, 'user_id', id)\n}\n\nexport async function lockUserByEmail(\n  trx: Transaction<Database>,\n  email: string,\n): Promise<UserRow | undefined> {\n  return lockUser(trx, 'email', email)\n}\n\nasync function lockUser(\n  trx: Transaction<Database>,\n  column: 'user_id' | 'email',\n  value: string,\n): Promise<UserRow | undefined> {\n  const user = await trx\n    .selectFrom('user')\n    .where(column, '=', value)\n    .selectAll('user')\n    .forUpdate()\n    .executeTakeFirst()\n\n  return user\n}\n\nexport async function setUserEmail(\n  db: Kysely<Database>,\n  id: string,\n  email: string,\n): Promise<void> {\n  await db\n    .updateTable('user')\n    .where('user_id', '=', id)\n    .set({ email })\n    .execute()\n}\n"
  },
  {
    "path": "example/src/user/user.service.ts",
    "content": "import * as userRepository from './user.repository'\nimport * as authTokenService from '../authentication/auth-token.service'\n\nimport { Kysely, Transaction } from 'kysely'\nimport { Database } from '../database'\nimport { SignedInUser } from './signed-in-user'\nimport { CreateAnonymousUserRequest, User } from './user'\nimport { UserRow } from './user.table'\n\nexport async function createAnonymousUser(\n  db: Kysely<Database>,\n  request: CreateAnonymousUserRequest,\n): Promise<SignedInUser> {\n  const user = await userRepository.insertUser(db, {\n    first_name: request.firstName,\n    last_name: request.lastName,\n  })\n\n  const refreshToken = await authTokenService.createRefreshToken(\n    db,\n    user.user_id,\n  )\n\n  const authToken = await authTokenService.createAuthToken(db, refreshToken)\n\n  return {\n    refreshToken,\n    authToken,\n    user: userRowToUser(user),\n  }\n}\n\nexport async function findUserById(\n  db: Kysely<Database>,\n  userId: string,\n): Promise<User | undefined> {\n  const userRow = await userRepository.findUserById(db, userId)\n\n  if (userRow) {\n    return userRowToUser(userRow)\n  }\n}\n\nexport async function lockUserById(\n  trx: Transaction<Database>,\n  id: string,\n): Promise<User | undefined> {\n  const userRow = await userRepository.lockUserById(trx, id)\n\n  if (userRow) {\n    return userRowToUser(userRow)\n  }\n}\n\nexport async function lockUserByEmail(\n  trx: Transaction<Database>,\n  email: string,\n): Promise<User | undefined> {\n  const userRow = await userRepository.lockUserByEmail(trx, email)\n\n  if (userRow) {\n    return userRowToUser(userRow)\n  }\n}\n\nexport async function setUserEmail(\n  db: Kysely<Database>,\n  userId: string,\n  email: string,\n): Promise<void> {\n  await userRepository.setUserEmail(db, userId, email)\n}\n\nexport function userRowToUser(user: UserRow): User {\n  return {\n    id: user.user_id,\n    firstName: user.first_name,\n    lastName: user.last_name,\n    email: user.email,\n  }\n}\n"
  },
  {
    "path": "example/src/user/user.table.ts",
    "content": "import { Generated, Insertable, Selectable, Updateable } from 'kysely'\n\nexport interface UserTable {\n  user_id: Generated<string>\n  first_name: string | null\n  last_name: string | null\n  email: string | null\n  created_at: Generated<Date>\n}\n\nexport type UserRow = Selectable<UserTable>\nexport type InsertableUserRow = Insertable<UserTable>\nexport type UpdateableUserRow = Updateable<UserTable>\n"
  },
  {
    "path": "example/src/user/user.ts",
    "content": "import { ajv } from '../util/ajv'\n\nexport interface User {\n  id: string\n  firstName: string | null\n  lastName: string | null\n  email: string | null\n}\n\nexport interface CreateAnonymousUserRequest {\n  firstName?: string\n  lastName?: string\n}\n\nexport const validateCreateAnonymousUserRequest =\n  ajv.compile<CreateAnonymousUserRequest>({\n    type: 'object',\n    properties: {\n      firstName: {\n        type: 'string',\n      },\n      lastName: {\n        type: 'string',\n      },\n    },\n  })\n"
  },
  {
    "path": "example/src/util/ajv.ts",
    "content": "import Ajv from 'ajv'\n\nexport const ajv = new Ajv()\n"
  },
  {
    "path": "example/src/util/errors.ts",
    "content": "export type AuthenticationErrors =\n  | 'NoUserIdParameter'\n  | 'InvalidAuthorizationHeader'\n  | 'InvalidAuthToken'\n  | 'ExpiredAuthToken'\n  | 'UserMismatch'\n  | 'UserOrRefreshTokenNotFound'\n\nexport type UserApiErrors = 'InvalidUser' | 'UserNotFound'\n\nexport type SignInMethodApiErrors =\n  | 'InvalidSignInMethod'\n  | 'UserAlreadyHasSignInMethod'\n  | 'PasswordTooWeak'\n  | 'PasswordTooLong'\n  | 'InvalidCredentials'\n  | 'InvalidRefreshToken'\n  | 'RefreshTokenUserIdMismatch'\n\nexport type ErrorCode =\n  | 'UnknownError'\n  | AuthenticationErrors\n  | UserApiErrors\n  | SignInMethodApiErrors\n\nexport type ErrorStatus = 400 | 401 | 403 | 404 | 409 | 500\n\nexport class ControllerError extends Error {\n  readonly status: ErrorStatus\n  readonly code: ErrorCode\n  readonly data?: any\n\n  constructor(\n    status: ErrorStatus,\n    code: ErrorCode,\n    message: string,\n    data?: any,\n  ) {\n    super(message)\n    this.status = status\n    this.code = code\n    this.data = data\n  }\n\n  toJSON() {\n    return {\n      error: { code: this.code, message: this.message },\n    }\n  }\n}\n\nexport class UserNotFoundError extends Error {}\n"
  },
  {
    "path": "example/src/util/object.ts",
    "content": "export function isObject(value: unknown): value is Record<string, any> {\n  return typeof value === 'object' && value !== null\n}\n"
  },
  {
    "path": "example/test/test-config.ts",
    "content": "import { ConnectionConfig } from 'pg'\nimport { Config } from '../src/config'\n\nexport interface TestConfig extends Config {\n  readonly adminDatabase: ConnectionConfig\n}\n\nexport const testConfig: TestConfig = {\n  port: 3001,\n  authTokenSecret: 'a498a5cf13a8194a2477f9284df34af3954fad3dc8459e343a',\n  authTokenExpiryDuration: '2h',\n  database: {\n    host: 'localhost',\n    database: 'kysely_koa_example_test',\n    user: 'postgres',\n  },\n  adminDatabase: {\n    host: 'localhost',\n    database: 'postgres',\n    user: 'postgres',\n  },\n}\n"
  },
  {
    "path": "example/test/test-context.ts",
    "content": "import * as path from 'path'\nimport axios from 'axios'\nimport { promises as fs } from 'fs'\nimport {\n  FileMigrationProvider,\n  Kysely,\n  Migrator,\n  PostgresDialect,\n  sql,\n} from 'kysely'\n\nimport { testConfig } from './test-config'\nimport { App } from '../src/app'\nimport { Database } from '../src/database'\nimport { User } from '../src/user/user'\nimport { Pool } from 'pg'\n\nexport class TestContext {\n  #app?: App\n\n  request = axios.create({\n    baseURL: `http://localhost:${testConfig.port}`,\n    validateStatus: () => true,\n  })\n\n  get db(): Kysely<Database> {\n    return this.#app!.db\n  }\n\n  before = async (): Promise<void> => {\n    const adminDb = new Kysely<any>({\n      dialect: new PostgresDialect({\n        pool: new Pool(testConfig.adminDatabase),\n      }),\n    })\n\n    // Create our test database\n    const { database } = testConfig.database\n    await sql`drop database if exists ${sql.id(database!)}`.execute(adminDb)\n    await sql`create database ${sql.id(database!)}`.execute(adminDb)\n    await adminDb.destroy()\n\n    // Now connect to the test database and run the migrations\n    const db = new Kysely<any>({\n      dialect: new PostgresDialect({\n        pool: new Pool(testConfig.database),\n      }),\n    })\n\n    const migrator = new Migrator({\n      db,\n      provider: new FileMigrationProvider({\n        fs,\n        path,\n        migrationFolder: path.join(__dirname, '../src/migrations'),\n      }),\n    })\n\n    await migrator.migrateToLatest()\n    await db.destroy()\n  }\n\n  after = async (): Promise<void> => {\n    // Nothing to do here at the moment\n  }\n\n  beforeEach = async (): Promise<void> => {\n    this.#app = new App(testConfig)\n\n    // Clear the database\n    await this.db.deleteFrom('user').execute()\n\n    await this.#app.start()\n  }\n\n  afterEach = async (): Promise<void> => {\n    await this.#app?.stop()\n    this.#app = undefined\n  }\n\n  createUser = async (): Promise<{\n    user: User\n    authToken: string\n    refreshToken: string\n  }> => {\n    const res = await this.request.post(`/api/v1/user`, {\n      firstName: 'Test',\n      lastName: 'Testerson',\n    })\n\n    return res.data\n  }\n}\n"
  },
  {
    "path": "example/test/user/user.test.ts",
    "content": "import { expect } from 'chai'\n\nimport { TestContext } from '../test-context'\nimport { User } from '../../src/user/user'\nimport { AxiosResponse } from 'axios'\n\nconst EMAIL = 'foo@bar.fake'\nconst PASSWORD = '12345678'\n\ndescribe('user tests', () => {\n  const ctx = new TestContext()\n\n  before(ctx.before)\n  beforeEach(ctx.beforeEach)\n\n  after(ctx.after)\n  afterEach(ctx.afterEach)\n\n  it('should create an anonoymous user', async () => {\n    const res = await ctx.request.post(`/api/v1/user`, {\n      firstName: 'Anon',\n    })\n\n    expect(res.status).to.equal(201)\n    expect(res.data.user.firstName).to.equal('Anon')\n    expect(res.data.user.lastName).to.equal(null)\n    expect(res.data.user.email).to.equal(null)\n\n    // The returned auth token should be usable.\n    const getRes = await ctx.request.get<{ user: User }>(\n      `/api/v1/user/${res.data.user.id}`,\n      createAuthHeaders(res.data.authToken),\n    )\n\n    expect(getRes.status).to.equal(200)\n    expect(getRes.data.user).to.eql(res.data.user)\n  })\n\n  it('should get user by id', async () => {\n    const { user, authToken } = await ctx.createUser()\n\n    const res = await ctx.request.get<{ user: User }>(\n      `/api/v1/user/${user.id}`,\n      createAuthHeaders(authToken),\n    )\n\n    expect(res.status).to.equal(200)\n    expect(res.data).to.eql({ user })\n  })\n\n  it('should add a password sign in method for a user', async () => {\n    const { user, authToken } = await ctx.createUser()\n    const res = await createPasswordSignInMethod(user.id, authToken)\n\n    expect(res.status).to.equal(201)\n    expect(res.data.success).to.equal(true)\n  })\n\n  it('should sign in a user', async () => {\n    const { user, authToken } = await ctx.createUser()\n    await createPasswordSignInMethod(user.id, authToken)\n\n    const res = await ctx.request.post(`/api/v1/user/sign-in`, {\n      email: EMAIL,\n      password: PASSWORD,\n    })\n\n    expect(res.status).to.equal(200)\n\n    // The returned auth token should be usable.\n    const getRes = await ctx.request.get<{ user: User }>(\n      `/api/v1/user/${res.data.user.id}`,\n      createAuthHeaders(authToken),\n    )\n\n    expect(getRes.status).to.equal(200)\n    expect(getRes.data.user).to.eql(res.data.user)\n  })\n\n  it('should fail to sign in user with the wrong password', async () => {\n    const { user, authToken } = await ctx.createUser()\n    await createPasswordSignInMethod(user.id, authToken)\n\n    const res = await ctx.request.post(`/api/v1/user/sign-in`, {\n      email: EMAIL,\n      password: 'wrong password',\n    })\n\n    expect(res.status).to.equal(401)\n    expect(res.data).to.eql({\n      error: {\n        code: 'InvalidCredentials',\n        message: 'wrong email or password',\n      },\n    })\n\n    // Only the one refresh token created for the anonymous user should exists.\n    expect(\n      await ctx.db\n        .selectFrom('refresh_token')\n        .select('refresh_token.user_id')\n        .execute(),\n    ).to.have.length(1)\n  })\n\n  it('should sign out a user', async () => {\n    const { user, authToken, refreshToken } = await ctx.createUser()\n\n    const res = await ctx.request.post(\n      `/api/v1/user/${user.id}/sign-out`,\n      { refreshToken },\n      createAuthHeaders(authToken),\n    )\n\n    expect(res.status).to.equal(200)\n\n    // The auth token should no longer be usable.\n    const getRes = await ctx.request.get(\n      `/api/v1/user/${user.id}`,\n      createAuthHeaders(authToken),\n    )\n\n    expect(getRes.status).to.equal(404)\n    expect(getRes.data.error.code).to.equal('UserOrRefreshTokenNotFound')\n  })\n\n  function createAuthHeaders(authToken: string) {\n    return {\n      headers: {\n        Authorization: `Bearer ${authToken}`,\n      },\n    }\n  }\n\n  async function createPasswordSignInMethod(\n    userId: string,\n    authToken: string,\n  ): Promise<AxiosResponse<{ success: true }>> {\n    return await ctx.request.post<{ success: true }>(\n      `/api/v1/user/${userId}/sign-in-methods`,\n      { email: EMAIL, password: PASSWORD },\n      createAuthHeaders(authToken),\n    )\n  }\n})\n"
  },
  {
    "path": "example/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"target\": \"ESNext\",\n    \"declaration\": true,\n    \"outDir\": \"./dist\",\n    \"strict\": true,\n    \"noImplicitAny\": true\n  },\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "jsr.json",
    "content": "{\n  \"$schema\": \"https://jsr.io/schema/config-file.v1.json\",\n  \"name\": \"@kysely/kysely\",\n  \"version\": \"0.28.14\",\n  \"license\": \"MIT\",\n  \"exports\": {\n    \".\": \"./src/index.ts\",\n    \"./helpers/mysql\": \"./src/helpers/mysql.ts\",\n    \"./helpers/mssql\": \"./src/helpers/mssql.ts\",\n    \"./helpers/postgres\": \"./src/helpers/postgres.ts\",\n    \"./helpers/sqlite\": \"./src/helpers/sqlite.ts\"\n  },\n  \"publish\": {\n    \"include\": [\n      \"LICENSE\",\n      \"README.md\",\n      \"src/**/*.ts\"\n    ]\n  }\n}\n"
  },
  {
    "path": "outdated-typescript.d.ts",
    "content": "import type { KyselyTypeError } from './dist/cjs/util/type-error'\n\ndeclare const Kysely: KyselyTypeError<'The installed TypeScript version is outdated and cannot guarantee type-safety with Kysely. Please upgrade to version 4.6 or newer.'>\ndeclare const RawBuilder: KyselyTypeError<'The installed TypeScript version is outdated and cannot guarantee type-safety with Kysely. Please upgrade to version 4.6 or newer.'>\ndeclare const sql: KyselyTypeError<'The installed TypeScript version is outdated and cannot guarantee type-safety with Kysely. Please upgrade to version 4.6 or newer.'>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"kysely\",\n  \"version\": \"0.28.14\",\n  \"description\": \"Type safe SQL query builder\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/kysely-org/kysely.git\"\n  },\n  \"homepage\": \"https://kysely.dev\",\n  \"keywords\": [\n    \"query\",\n    \"builder\",\n    \"query builder\",\n    \"sql\",\n    \"typescript\",\n    \"postgres\",\n    \"postgresql\",\n    \"mysql\",\n    \"sqlite\",\n    \"mssql\",\n    \"ms sql server\",\n    \"sql server\",\n    \"type-safe\",\n    \"type-safety\",\n    \"plugins\"\n  ],\n  \"engines\": {\n    \"node\": \">=20.0.0\"\n  },\n  \"main\": \"dist/cjs/index.js\",\n  \"module\": \"dist/esm/index.js\",\n  \"typesVersions\": {\n    \"<4.6\": {\n      \"*\": [\n        \"outdated-typescript.d.ts\"\n      ]\n    }\n  },\n  \"files\": [\n    \"dist\",\n    \"helpers\",\n    \"outdated-typescript.d.ts\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/esm/index.js\",\n      \"require\": \"./dist/cjs/index.js\",\n      \"default\": \"./dist/cjs/index.js\"\n    },\n    \"./helpers/postgres\": {\n      \"import\": \"./dist/esm/helpers/postgres.js\",\n      \"require\": \"./dist/cjs/helpers/postgres.js\",\n      \"default\": \"./dist/cjs/helpers/postgres.js\"\n    },\n    \"./helpers/mysql\": {\n      \"import\": \"./dist/esm/helpers/mysql.js\",\n      \"require\": \"./dist/cjs/helpers/mysql.js\",\n      \"default\": \"./dist/cjs/helpers/mysql.js\"\n    },\n    \"./helpers/mssql\": {\n      \"import\": \"./dist/esm/helpers/mssql.js\",\n      \"require\": \"./dist/cjs/helpers/mssql.js\",\n      \"default\": \"./dist/cjs/helpers/mssql.js\"\n    },\n    \"./helpers/sqlite\": {\n      \"import\": \"./dist/esm/helpers/sqlite.js\",\n      \"require\": \"./dist/cjs/helpers/sqlite.js\",\n      \"default\": \"./dist/cjs/helpers/sqlite.js\"\n    }\n  },\n  \"sideEffects\": false,\n  \"scripts\": {\n    \"clean\": \"rm -rf dist & rm -rf test/node/dist & rm -rf test/browser/bundle.js & rm -rf helpers\",\n    \"bench:ts\": \"pnpm build && cd ./test/ts-benchmarks && node --experimental-strip-types ./index.ts\",\n    \"test\": \"pnpm build && pnpm test:node:build && pnpm test:node:run && pnpm test:typings && pnpm test:esmimports && pnpm test:exports\",\n    \"test:node:build\": \"tsc -p test/node\",\n    \"test:node\": \"pnpm build && pnpm test:node:build && pnpm test:node:run\",\n    \"test:node:run\": \"mocha --timeout 15000 test/node/dist/**/*.test.js\",\n    \"test:browser:build\": \"rm -rf test/browser/bundle.js && esbuild test/browser/main.ts --bundle --outfile=test/browser/bundle.js\",\n    \"test:browser\": \"pnpm build && pnpm test:browser:build && node test/browser/test.js\",\n    \"test:bun\": \"pnpm build && bun link && cd test/bun && bun install && bun run test\",\n    \"test:cloudflare-workers\": \"pnpm build && pnpm -r test --filter kysely-cloudflare-workers-test\",\n    \"test:deno\": \"deno run --allow-env --allow-read --allow-net --no-lock test/deno/local.test.ts && deno run --allow-env --allow-read --allow-net --no-lock test/deno/cdn.test.ts\",\n    \"test:typings\": \"tsd test/typings\",\n    \"test:esmimports\": \"node scripts/check-esm-imports.js\",\n    \"test:esbuild\": \"esbuild --bundle --platform=node --external:pg-native dist/esm/index.js --outfile=/dev/null\",\n    \"test:exports\": \"attw --pack . && node scripts/check-exports.js\",\n    \"test:jsdocs\": \"deno check --doc-only --no-lock --unstable-sloppy-imports --config=\\\"deno.check.json\\\" ./src\",\n    \"test:outdatedts\": \"pnpm build && cd test/outdated-ts && pnpm i && pnpm test\",\n    \"lint:deno\": \"deno lint --config=\\\"deno.lint.json\\\" ./src\",\n    \"prettier\": \"prettier --write 'src/**/*.ts' 'test/**/*.ts'\",\n    \"build\": \"pnpm clean && (pnpm build:esm & pnpm build:cjs) && pnpm script:module-fixup && pnpm script:copy-interface-doc\",\n    \"build:esm\": \"tsc -p tsconfig.json && pnpm script:add-deno-type-references\",\n    \"build:cjs\": \"tsc -p tsconfig-cjs.json\",\n    \"script:module-fixup\": \"node scripts/module-fixup.js\",\n    \"script:copy-interface-doc\": \"node scripts/copy-interface-documentation.js\",\n    \"script:add-deno-type-references\": \"node scripts/add-deno-type-references.js\",\n    \"script:align-versions\": \"node --experimental-strip-types scripts/align-versions.mts\",\n    \"script:generate-site-examples\": \"node scripts/generate-site-examples.js\",\n    \"script:exclude-test-files-for-backwards-compat\": \"node --experimental-strip-types scripts/exclude-test-files-for-backwards-compat.mts\",\n    \"script:remove-global-augmentations\": \"node --experimental-strip-types scripts/remove-global-augmentations.mts\",\n    \"prepublishOnly\": \"pnpm build && pnpm test:exports\",\n    \"version\": \"pnpm script:align-versions && git add .\"\n  },\n  \"author\": \"Sami Koskimäki <sami@jakso.me>\",\n  \"license\": \"MIT\",\n  \"contributors\": [\n    \"Sami Koskimäki <sami@jakso.me>\",\n    \"Igal Klebanov <igalklebanov@gmail.com>\"\n  ],\n  \"devDependencies\": {\n    \"@arethetypeswrong/cli\": \"^0.18.2\",\n    \"@ark/attest\": \"^0.56.0\",\n    \"@types/better-sqlite3\": \"^7.6.13\",\n    \"@types/chai\": \"^5.2.3\",\n    \"@types/chai-as-promised\": \"^8.0.2\",\n    \"@types/mocha\": \"^10.0.10\",\n    \"@types/node\": \"^25.5.0\",\n    \"@types/pg\": \"^8.18.0\",\n    \"@types/pg-cursor\": \"^2.7.2\",\n    \"@types/semver\": \"^7.7.1\",\n    \"@types/sinon\": \"^21.0.0\",\n    \"better-sqlite3\": \"^12.8.0\",\n    \"chai\": \"^6.2.2\",\n    \"chai-as-promised\": \"^8.0.2\",\n    \"esbuild\": \"^0.27.4\",\n    \"jsr\": \"^0.14.3\",\n    \"lodash\": \"^4.17.23\",\n    \"mocha\": \"^11.7.5\",\n    \"mysql2\": \"^3.20.0\",\n    \"pathe\": \"^2.0.3\",\n    \"pg\": \"^8.20.0\",\n    \"pg-cursor\": \"^2.19.0\",\n    \"pkg-types\": \"^2.3.0\",\n    \"playwright\": \"^1.58.2\",\n    \"prettier\": \"^3.8.1\",\n    \"semver\": \"^7.7.4\",\n    \"sinon\": \"^21.0.3\",\n    \"std-env\": \"^4.0.0\",\n    \"tarn\": \"^3.0.2\",\n    \"tedious\": \"^19.2.1\",\n    \"tsd\": \"^0.33.0\",\n    \"typescript\": \"~5.9.3\"\n  },\n  \"packageManager\": \"pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264\"\n}\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - './site'\n  - './test/cloudflare-workers'\n\n# Allow (true) or disallow (false) script execution.\n# https://pnpm.io/settings#allowbuilds\nallowBuilds:\n  better-sqlite3@12.8.0: true\n  core-js: false # site dependency, useless scripts\n  core-js-pure: false # site dependency, useless scripts\n  esbuild@0.27.4: true\n  sharp: false # wrangler dependency, useless scripts\n  workerd@1.20260317.1: true # wrangler@4.75.0 dependency\n\n# All transitive dependencies must be resolved from a trusted source.\n# Packages from trusted sources are considered safer, as they are typically subject\n# to more reliable verification and scanning for malware and vulnerabilities.\n# https://pnpm.io/settings#blockexoticsubdeps\nblockExoticSubdeps: true\n\n# The minimum number of minutes that must pass after a version is published before\n# pnpm will install it.\n# https://pnpm.io/settings#minimumreleaseage\nminimumReleaseAge: 1440 # 1 day old in minutes.\n\n# Fail if a package's trust level has decreased compared to previous releases.\n# https://pnpm.io/settings#trustpolicy\ntrustPolicy: no-downgrade\n\n# A list of package selectors that should be excluded from the trust policy check.\n# https://pnpm.io/settings#trustpolicyexclude\ntrustPolicyExclude:\n  - semver@5.7.2 || 6.3.1 # tsd@0.20.0 || @docusaurus/core@3.9.2 - https://socket.dev/npm/package/semver/overview/5.7.2 || https://socket.dev/npm/package/semver/overview/6.3.1\n"
  },
  {
    "path": "scripts/add-deno-type-references.js",
    "content": "/**\n * This scripts adds a `/// <reference types=\"./file.d.ts\" />` directive\n * at the beginning of each ESM JavaScript file so that they work with\n * deno.\n */\n\nconst fs = require('fs')\nconst path = require('path')\nconst forEachFile = require('./util/for-each-file')\n\nconst ESM_DIST_PATH = path.join(__dirname, '..', 'dist', 'esm')\n\nforEachFile(ESM_DIST_PATH, (filePath) => {\n  if (filePath.endsWith('.js')) {\n    const dTsFile = path.basename(filePath).replace(/\\.js$/, '.d.ts')\n    const content = fs.readFileSync(filePath, { encoding: 'utf-8' })\n\n    fs.writeFileSync(\n      filePath,\n      `/// <reference types=\"./${dTsFile}\" />\\n${content}`,\n    )\n  }\n})\n"
  },
  {
    "path": "scripts/align-versions.mts",
    "content": "/**\n * This script aligns docs site package.json AND jsr versions with\n * Kysely's version so we use only the latest published version in the docs and JSR publish.\n */\nimport { writeFileSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { dirname, join } from 'pathe'\nimport jsrJson from '../jsr.json' with { type: 'json' }\nimport pkgJson from '../package.json' with { type: 'json' }\nimport sitePkgJson from '../site/package.json' with { type: 'json' }\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nconst { version } = pkgJson\n\nwriteFileSync(\n  join(__dirname, '../site/package.json'),\n  JSON.stringify({ ...sitePkgJson, version }, null, 2) + '\\n',\n)\n\nwriteFileSync(\n  join(__dirname, '../jsr.json'),\n  JSON.stringify({ ...jsrJson, version }, null, 2) + '\\n',\n)\n"
  },
  {
    "path": "scripts/check-esm-imports.js",
    "content": "/**\n * This script goes through all source files and makes sure\n * imports end with '.js'. If they don't, the ESM version will\n * not work. ESM imports must have the full file name.\n */\n\nconst fs = require('fs')\nconst path = require('path')\nconst forEachFile = require('./util/for-each-file')\n\nlet errorsFound = false\n\nfunction checkDir(dir) {\n  forEachFile(dir, (filePath) => {\n    let errorsFoundInFile = false\n\n    if (filePath.endsWith('.ts')) {\n      for (const row of readLines(filePath)) {\n        if (isLocalImport(row) && !isDotJsImport(row)) {\n          if (!errorsFoundInFile) {\n            if (errorsFound) {\n              console.log(' ')\n            }\n\n            console.log(`invalid imports in file ${filePath}`)\n            errorsFoundInFile = true\n          }\n\n          console.log(row)\n          errorsFound = true\n        }\n      }\n    }\n  })\n}\n\nfunction readLines(filePath) {\n  const data = fs.readFileSync(filePath).toString('utf-8')\n  return data.split('\\n')\n}\n\nfunction isLocalImport(row) {\n  return /from ['\"]\\./.test(row)\n}\n\nfunction isDotJsImport(row) {\n  return /.js['\"][\\n\\t\\s]*$/.test(row)\n}\n\ncheckDir(path.join(__dirname, '..', 'src'))\n\nif (errorsFound) {\n  console.log(' ')\n  console.log('check-esm-imports.js failed!')\n  process.exit(1)\n}\n"
  },
  {
    "path": "scripts/check-exports.js",
    "content": "/**\n * This script ensures all files in a path are exported in the index.ts file.\n * For now it only checks the operation-node folder, as we've had issues with\n * missing exports there.\n */\n\nconst fs = require('node:fs')\nconst path = require('node:path')\nconst forEachFile = require('./util/for-each-file')\n\nlet errorsFound = false\n\nfunction checkExports(dir) {\n  const indexFileContents = fs.readFileSync(\n    path.join(__dirname, '..', 'src/index.ts'),\n    'utf-8',\n  )\n\n  forEachFile(dir, (filePath) => {\n    if (filePath.endsWith('.ts')) {\n      const expectedExportPath = filePath.replace(\n        /^.+\\/src\\/(.+)\\.ts$/,\n        \"'./$1.js'\",\n      )\n\n      if (!indexFileContents.includes(expectedExportPath)) {\n        console.log(`Missing export: ${expectedExportPath}`)\n        errorsFound = true\n      }\n    }\n  })\n}\n\ncheckExports(path.join(__dirname, '..', 'src/operation-node'))\n\nif (errorsFound) {\n  console.log(' ')\n  console.log('check-exports.js failed!')\n  process.exit(1)\n}\n"
  },
  {
    "path": "scripts/copy-interface-documentation.js",
    "content": "/**\n * This script goes through all generated type definition files and copies\n * method/property documentation from interfaces to the implementing methods\n * IF the implementation doesn't have its own documentation.\n *\n * This is done for convenience: users can cmd-click method names and immediately\n * see the documentation. If we don't do this, users need to cmd-click the method\n * and then manually find the correct interface that contains the documentation.\n *\n * Hovering over a method/property works even without this script, but not all\n * people are happy reading docs from the small hovering window.\n */\n\nconst fs = require('fs')\nconst path = require('path')\nconst forEachFile = require('./util/for-each-file')\n\nconst DIST_PATH = path.join(__dirname, '..', 'dist')\n\nconst PROPERTY_REGEX = /^\\s+(?:get )?(?:readonly )?(?:abstract )?(\\w+)[\\(:<]/\nconst OBJECT_REGEXES = [\n  /^(?:export )?declare (?:abstract )?class (\\w+)/,\n  /^(?:export )?interface (\\w+)/,\n]\nconst GENERIC_ARGUMENTS_REGEX = /<[\\w\"'`,{}=|\\[\\] ]+>/g\nconst JSDOC_START_REGEX = /^\\s+\\/\\*\\*/\nconst JSDOC_END_REGEX = /^\\s+\\*\\//\n\nfunction main() {\n  for (const distSubDir of ['cjs', 'esm']) {\n    const subDirPath = path.join(DIST_PATH, distSubDir)\n    const files = []\n\n    if (!fs.existsSync(subDirPath)) {\n      continue\n    }\n\n    forEachFile(subDirPath, (filePath) => {\n      if (filePath.endsWith('.d.ts')) {\n        const file = {\n          path: filePath,\n          lines: readLines(filePath),\n        }\n\n        file.objects = parseObjects(file)\n\n        if (file.objects.length > 0) {\n          files.push(file)\n        }\n      }\n    })\n\n    copyDocumentation(files)\n  }\n}\n\nfunction readLines(filePath) {\n  const data = fs.readFileSync(filePath).toString('utf-8')\n  return data.split('\\n')\n}\n\n/**\n * Parses all object (class, interface) declarations from the given\n * type declaration file.\n */\nfunction parseObjects(file) {\n  const objects = []\n  let lineIdx = 0\n\n  while (lineIdx < file.lines.length) {\n    for (const regex of OBJECT_REGEXES) {\n      const objectMatch = regex.exec(file.lines[lineIdx])\n\n      if (objectMatch) {\n        const object = {\n          name: objectMatch[1],\n          lineIdx,\n          implements: parseImplements(file.lines[lineIdx]),\n          properties: [],\n        }\n\n        while (!file.lines[++lineIdx].startsWith('}')) {\n          const propertyMatch = PROPERTY_REGEX.exec(file.lines[lineIdx])\n\n          if (propertyMatch) {\n            const property = {\n              name: propertyMatch[1],\n              lineIdx: lineIdx,\n              doc: parseDocumentation(file.lines, lineIdx),\n            }\n\n            Object.defineProperty(property, 'object', { value: object })\n            object.properties.push(property)\n          }\n        }\n\n        Object.defineProperty(object, 'file', { value: file })\n        objects.push(object)\n\n        continue\n      }\n    }\n\n    ++lineIdx\n  }\n\n  return objects\n}\n\n/**\n * Given an object declaration line like\n *\n *   export class A extends B implements C, D<number> {\n *\n * or\n *\n *   interface A<T> extends B<T> {\n *\n * extracts the names of the extended and implemented objects.\n * The first example would return ['B', 'C', 'D'] and the second\n * would return ['B'].\n */\nfunction parseImplements(line) {\n  if (!line.endsWith('{')) {\n    console.warn(\n      `skipping object declaration \"${line}\". Expected it to end with \"{\"'`,\n    )\n    return []\n  }\n\n  // Remove { from the end.\n  line = line.substring(0, line.length - 1)\n\n  // Strip generics. We need to do this in a loop to strip nested generics.\n  while (line.includes('<')) {\n    let strippedLine = line.replace(GENERIC_ARGUMENTS_REGEX, '')\n\n    if (strippedLine === line) {\n      console.warn(`unable to strip generics from \"${line}\"`)\n      return []\n    }\n\n    line = strippedLine\n  }\n\n  if (line.includes('extends')) {\n    line = line.split('extends')[1].replace('implements', ',')\n  } else if (line.includes('implements')) {\n    line = line.split('implements')[1]\n  } else {\n    return []\n  }\n\n  return line.split(',').map((it) => it.trim())\n}\n\n/**\n * Given the line index of a property (method, getter) declaration\n * extracts the jsdoc comment above it if one exists.\n */\nfunction parseDocumentation(lines, propertyLineIdx) {\n  const doc = []\n  let lineIdx = propertyLineIdx - 1\n\n  if (JSDOC_END_REGEX.test(lines[lineIdx])) {\n    doc.push(lines[lineIdx])\n    --lineIdx\n\n    while (!JSDOC_START_REGEX.test(lines[lineIdx])) {\n      doc.push(lines[lineIdx])\n      --lineIdx\n    }\n\n    doc.push(lines[lineIdx])\n    return doc.reverse()\n  }\n\n  return undefined\n}\n\nfunction copyDocumentation(files) {\n  for (const file of files) {\n    for (const object of file.objects) {\n      const undocumentedProperties = new Set()\n\n      // Only keep one undocumented property by same name.\n      object.properties = object.properties.filter((it) => {\n        if (it.doc) {\n          return true\n        }\n\n        if (undocumentedProperties.has(it.name)) {\n          return false\n        }\n\n        undocumentedProperties.add(it.name)\n        return true\n      })\n    }\n  }\n\n  for (const file of files) {\n    for (const object of file.objects.slice().reverse()) {\n      for (const property of object.properties.slice().reverse()) {\n        if (!property.doc) {\n          const docProperty = findDocProperty(files, object, property.name)\n\n          if (docProperty) {\n            file.lines.splice(property.lineIdx, 0, ...docProperty.doc)\n          }\n        }\n      }\n    }\n\n    fs.writeFileSync(file.path, file.lines.join('\\n'))\n  }\n}\n\nfunction findDocProperty(files, object, propertyName) {\n  for (const interfaceName of object.implements) {\n    const interfaceObject = findObject(files, interfaceName)\n\n    if (!interfaceObject) {\n      continue\n    }\n\n    const interfaceProperty = interfaceObject.properties.find(\n      (it) => it.name === propertyName,\n    )\n\n    if (interfaceProperty?.doc) {\n      return interfaceProperty\n    }\n\n    // Search all parents even if this object didn't have the\n    // proprty. It may be defined and documented in an ancestor.\n    const doc = findDocProperty(files, interfaceObject, propertyName)\n\n    if (doc) {\n      return doc\n    }\n  }\n\n  return undefined\n}\n\nfunction findObject(files, objectName) {\n  for (const file of files) {\n    for (const object of file.objects) {\n      if (object.name === objectName) {\n        return object\n      }\n    }\n  }\n\n  return undefined\n}\n\nmain()\n"
  },
  {
    "path": "scripts/exclude-test-files-for-backwards-compat.mts",
    "content": "import { unlink } from 'node:fs/promises'\nimport { dirname, resolve } from 'pathe'\nimport { readPackageJSON, readTSConfig, writeTSConfig } from 'pkg-types'\nimport { lt } from 'semver'\n\nconst { devDependencies } = await readPackageJSON()\n\nconst typescriptVersion = devDependencies!.typescript.replace(/^[~^]/, '')\n\nconsole.log('typescriptVersion', typescriptVersion)\n\nif (lt(typescriptVersion, '5.2.0')) {\n  const tsconfigPath = resolve(\n    dirname(new URL(import.meta.url).pathname),\n    '../test/node/tsconfig.json',\n  )\n\n  const tsconfig = await readTSConfig(tsconfigPath)\n\n  const updatedTSConfig = {\n    ...tsconfig,\n    // `using` keyword support was only added in 5.2.0\n    exclude: (tsconfig.exclude || []).concat('src/async-dispose.test.ts'),\n  }\n\n  await writeTSConfig(tsconfigPath, updatedTSConfig)\n\n  console.log(\n    `Updated ${tsconfigPath} to exclude async-dispose.test.ts`,\n    JSON.stringify(updatedTSConfig, null, 2),\n  )\n}\n\nif (lt(typescriptVersion, '5.4.0')) {\n  // inference from generics was only fixed in 5.4.0, before that you had to explicitly pass type arguments, and the inferred results were wider.\n  const typingsTestFilePath = resolve(\n    dirname(new URL(import.meta.url).pathname),\n    '../test/typings/test-d/generic.test-d.ts',\n  )\n\n  await unlink(typingsTestFilePath)\n\n  console.log(`Deleted ${typingsTestFilePath}`)\n}\n"
  },
  {
    "path": "scripts/generate-site-examples.js",
    "content": "/**\n * This script goes through all generated type definitions and creates\n * playground examples in the site for all code examples that are\n * annotated using the `<!-- siteExample(category: string, name: string, prority: int) -->\n * comment.\n */\n\nconst fs = require('fs')\nconst path = require('path')\nconst forEachFile = require('./util/for-each-file')\nconst _ = require('lodash')\n\nconst ESM_PATH = path.join(__dirname, '..', 'dist', 'esm')\nconst SITE_EXAMPLE_PATH = path.join(__dirname, '..', 'site', 'docs', 'examples')\n\nconst SITE_EXAMPLE_START_REGEX = /<!--\\s*siteExample\\(/\nconst SITE_EXAMPLE_ANNOTATION_REGEX =\n  /<!--\\s*siteExample\\(\"([^\"]+)\",\\s*\"([^\"]+)\",\\s*(\\d+)\\s*\\)\\s*-->/\n\nconst CODE_BLOCK_START_REGEX = /\\*\\s*```/\nconst CODE_BLOCK_END_REGEX = /\\*\\s*```/\nconst COMMENT_LINE_REGEX = /\\*\\s*(.*)/\nconst CODE_LINE_REGEX = /\\*(.*)/\n\nconst moreExamplesByCategory = {\n  select: {\n    'select method':\n      'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select',\n    'selectAll method':\n      'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll',\n    'selectFrom method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom',\n  },\n  where: {\n    'where method':\n      'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where',\n    'whereRef method':\n      'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef',\n  },\n  join: {\n    'innerJoin method':\n      'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin',\n    'leftJoin method':\n      'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin',\n    'rightJoin method':\n      'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin',\n    'fullJoin method':\n      'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin',\n  },\n  insert: {\n    'values method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values',\n    'onConflict method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict',\n    'returning method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning',\n    'insertInto method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto',\n  },\n  update: {\n    'set method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#set',\n    'returning method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#returning',\n    'updateTable method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#updateTable',\n  },\n  delete: {\n    'deleteFrom method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#deleteFrom',\n    'returning method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/DeleteQueryBuilder.html#returning',\n  },\n  merge: {\n    'mergeInto method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#mergeInto',\n    'using method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/MergeQueryBuilder.html#using',\n    'whenMatched method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/WheneableMergeQueryBuilder.html#whenMatched',\n    'thenUpdateSet method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/MatchedThenableMergeQueryBuilder.html#thenUpdateSet',\n    'thenDelete method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/MatchedThenableMergeQueryBuilder.html#thenDelete',\n    'thenDoNothing method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/MatchedThenableMergeQueryBuilder.html#thenDoNothing',\n    'whenNotMatched method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/WheneableMergeQueryBuilder.html#whenNotMatched',\n    'thenInsertValues method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/NotMatchedThenableMergeQueryBuilder.html#thenInsertValues',\n  },\n  transactions: {\n    'transaction method':\n      'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#transaction',\n  },\n}\n\nfunction main() {\n  deleteAllExamples()\n\n  forEachFile(ESM_PATH, (filePath) => {\n    if (!filePath.endsWith('.d.ts')) {\n      return\n    }\n\n    const lines = readLines(filePath)\n    const state = {\n      filePath,\n      /** @type {string | null} */\n      line: null,\n      lineIndex: 0,\n      annotation: null,\n      inExample: false,\n      inCodeBlock: false,\n      commentLines: [],\n      codeLines: [],\n    }\n\n    for (let l = 0; l < lines.length; ++l) {\n      state.line = lines[l]\n      state.lineIndex = l + 1\n\n      if (state.inExample) {\n        if (state.inCodeBlock) {\n          if (isCodeBlockEnd(state)) {\n            writeSiteExample(state)\n            exitExample(state)\n          } else {\n            addCodeLine(state)\n          }\n        } else if (isCodeBlockStart(state)) {\n          enterCodeBlock(state)\n        } else {\n          addCommentLine(state)\n        }\n      } else if (isExampleStart(state)) {\n        enterExample(state)\n      }\n    }\n  })\n\n  overwritePlaygroundTypes()\n}\n\nfunction deleteAllExamples() {\n  for (const category of fs.readdirSync(SITE_EXAMPLE_PATH)) {\n    const folderPath = path.join(SITE_EXAMPLE_PATH, category)\n\n    if (!fs.statSync(folderPath).isFile()) {\n      for (const file of fs.readdirSync(folderPath)) {\n        const filePath = path.join(folderPath, file)\n\n        if (file.endsWith('.js') || file.endsWith('.mdx')) {\n          fs.unlinkSync(filePath)\n        }\n      }\n    }\n  }\n}\n\nfunction readLines(filePath) {\n  const data = fs.readFileSync(filePath).toString('utf-8')\n  return data.split('\\n')\n}\n\nfunction isCodeBlockEnd(state) {\n  return CODE_BLOCK_END_REGEX.test(state.line)\n}\n\nfunction writeSiteExample(state) {\n  const [, category, name, priority] = state.annotation\n  const code = trimEmptyLines(state.codeLines).join('\\n')\n  const comment = trimEmptyLines(state.commentLines).join('\\n')\n  const codeVariable = _.camelCase(name)\n\n  const fileName = `${priority.padStart(4, '0')}-${_.kebabCase(name)}`\n  const folderPath = path.join(SITE_EXAMPLE_PATH, category)\n  const filePath = path.join(folderPath, fileName)\n\n  const codeFile = `export const ${codeVariable} = \\`${deindent(code)\n    .replaceAll('`', '\\\\`')\n    .replaceAll('${', '\\\\${')}\\``\n\n  const parts = [\n    deindent(`\n      ---\n      title: '${name}'\n      ---\n\n      # ${name}\n    `),\n  ]\n\n  if (comment?.trim()) {\n    parts.push(comment, '')\n  }\n\n  parts.push(\n    deindent(`\n      import { Playground } from '../../../src/components/Playground'\n\n      import {\n        ${codeVariable}\n      } from './${fileName}'\n\n      <div style={{ marginBottom: '1em' }}>\n        <Playground code={${codeVariable}} />\n      </div>\n    `),\n  )\n\n  const moreExamples = buildMoreExamplesMarkdown(category)\n  if (moreExamples?.trim()) {\n    parts.push(moreExamples)\n  }\n\n  const exampleFile = parts.join('\\n')\n\n  if (!fs.existsSync(folderPath)) {\n    fs.mkdirSync(folderPath, { recursive: true })\n    fs.writeFileSync(\n      path.join(folderPath, '_category_.json'),\n      `{\n  \"label\": \"${_.startCase(category)}\",\n  \"position\": 0, // TODO: set the position of the category.\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of using the ${category} functionality.\" // TODO: review this.\n  }\n}`,\n    )\n  }\n\n  fs.writeFileSync(filePath + '.js', codeFile, {})\n  fs.writeFileSync(filePath + '.mdx', exampleFile)\n}\n\nfunction buildMoreExamplesMarkdown(category) {\n  const links = moreExamplesByCategory[category]\n  if (!links) {\n    return undefined\n  }\n\n  const lines = [\n    ':::info[More examples]',\n    'The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),',\n    'but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always',\n    'just one hover away!',\n    '',\n    'For example, check out these sections:',\n  ]\n\n  for (const linkName of Object.keys(links)) {\n    lines.push(` - [${linkName}](${links[linkName]})`)\n  }\n\n  lines.push(':::\\n')\n\n  return lines.join('\\n')\n}\n\nfunction exitExample(state) {\n  state.annotation = null\n  state.inExample = false\n  state.inCodeBlock = false\n  state.commentLines = []\n  state.codeLines = []\n}\n\nfunction addCodeLine(state) {\n  const code = CODE_LINE_REGEX.exec(state.line)\n\n  if (!code) {\n    console.error(\n      `found invalid code block in a site example in ${state.filePath}:${state.lineIndex}`,\n    )\n\n    process.exit(1)\n  }\n\n  state.codeLines.push(code[1])\n}\n\nfunction isCodeBlockStart(state) {\n  return CODE_BLOCK_START_REGEX.test(state.line)\n}\n\nfunction enterCodeBlock(state) {\n  state.inCodeBlock = true\n}\n\nfunction addCommentLine(state) {\n  const comment = COMMENT_LINE_REGEX.exec(state.line)\n\n  if (!comment) {\n    console.error(\n      `found invalid comment in a site example in ${state.filePath}:${state.lineIndex}`,\n    )\n\n    process.exit(1)\n  }\n\n  state.commentLines.push(comment[1])\n}\n\nfunction isExampleStart(state) {\n  return SITE_EXAMPLE_START_REGEX.test(state.line)\n}\n\nfunction enterExample(state) {\n  state.annotation = SITE_EXAMPLE_ANNOTATION_REGEX.exec(state.line)\n\n  if (!state.annotation) {\n    console.error(\n      `found invalid site example annotation in ${state.filePath}:${state.lineIndex}`,\n    )\n\n    process.exit(1)\n  }\n\n  state.inExample = true\n}\n\nfunction deindent(str) {\n  let lines = str.split('\\n')\n\n  // Remove empty lines from the beginning.\n  while (lines[0].trim().length === 0) {\n    lines = lines.slice(1)\n  }\n\n  let ws = Number.MAX_SAFE_INTEGER\n  for (const line of lines) {\n    if (line.trim().length > 0) {\n      const [, wsExec] = /^(\\s*)/.exec(line) || []\n\n      if (wsExec != null && wsExec.length < ws) {\n        ws = wsExec.length\n      }\n    }\n  }\n\n  return lines.map((line) => line.substring(ws)).join('\\n')\n}\n\nfunction trimEmptyLines(lines) {\n  while (lines.length && lines[0].trim().length === 0) {\n    lines = lines.slice(1)\n  }\n\n  while (lines.length && lines[lines.length - 1].trim().length === 0) {\n    lines = lines.slice(0, lines.length - 1)\n  }\n\n  return lines\n}\n\nfunction overwritePlaygroundTypes() {\n  const jsdocsTestTypes = fs.readFileSync(\n    path.join(__dirname, '../deno.check.d.ts'),\n    { encoding: 'utf-8' },\n  )\n\n  const playgroundTypes = `// THIS FILE IS GENERATED BY \\`${path.relative('.', __filename)}\\`\n// DO NOT EDIT THIS FILE DIRECTLY\nexport const GENERATED_PLAYGROUND_EXAMPLE_TYPES = \\`${jsdocsTestTypes\n    .replace(/['\"`].*dist\\/.*['\"`]/g, \"'kysely'\")\n    .replaceAll('`', '\\\\`')}\\`;`\n\n  fs.writeFileSync(\n    path.join(__dirname, '../site/src/components/playground-example-types.ts'),\n    playgroundTypes,\n    { encoding: 'utf-8' },\n  )\n}\n\nmain()\n"
  },
  {
    "path": "scripts/module-fixup.js",
    "content": "/**\n * Adds a package.json file to both commonjs and ESM distribution\n * folders with a correct module type. This is needed in order to\n * be able to export both commonjs and ESM versions.\n *\n * This script also creates a dummy files for all `exports` in the\n * package.json to make CJS happy.\n */\n\nconst fs = require('fs')\nconst path = require('path')\nconst package = require('../package.json')\n\nconst ROOT_PATH = path.join(__dirname, '..')\nconst DIST_PATH = path.join(ROOT_PATH, 'dist')\n\nfor (const [folder, type] of [\n  ['cjs', 'commonjs'],\n  ['esm', 'module'],\n]) {\n  fs.writeFileSync(\n    path.join(DIST_PATH, folder, 'package.json'),\n    JSON.stringify({ type, sideEffects: false }),\n  )\n}\n\nfor (const ex of Object.keys(package.exports)) {\n  if (ex === '.') {\n    continue\n  }\n\n  const [, ...folders] = ex.split('/')\n  const fileName = folders.pop()\n\n  const [, ...targetFolders] = package.exports[ex].require.split('/')\n  const targetFileName = targetFolders.pop()\n  const target = path.posix.relative(\n    path.posix.join(ROOT_PATH, ...folders),\n    path.posix.join(ROOT_PATH, ...targetFolders, targetFileName),\n  )\n\n  fs.mkdirSync(path.join(ROOT_PATH, ...folders), {\n    recursive: true,\n  })\n\n  fs.writeFileSync(\n    path.join(ROOT_PATH, ...folders, fileName + '.js'),\n    `module.exports = require('${target}')`,\n  )\n\n  fs.writeFileSync(\n    path.join(ROOT_PATH, ...folders, fileName + '.d.ts'),\n    `export * from '${target}'`,\n  )\n}\n"
  },
  {
    "path": "scripts/remove-global-augmentations.mts",
    "content": "/**\n * This script removes global augmentations so we could publish to JSR.\n * https://github.com/denoland/deno/issues/23427\n */\nimport { readFileSync, writeFileSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { dirname, join } from 'pathe'\nimport ts from 'typescript'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nconst kyselyTSPath = join(__dirname, '../src/kysely.ts')\n\nconst sourceCode = readFileSync(kyselyTSPath, 'utf8')\n\nconst sourceFile = ts.createSourceFile(\n  kyselyTSPath,\n  sourceCode,\n  ts.ScriptTarget.Latest,\n  true,\n)\n\nconst printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed })\n\nconst nodesToRemove = new Set<ts.Node>()\n\nfunction visit(node: ts.Node) {\n  if (ts.isModuleDeclaration(node) && node.name.text === 'global') {\n    return nodesToRemove.add(node)\n  }\n\n  ts.forEachChild(node, visit)\n}\n\nvisit(sourceFile)\n\nconst newStatements = sourceFile.statements.filter(\n  (stmt) => !nodesToRemove.has(stmt),\n)\n\nconst newSourceFile = ts.factory.updateSourceFile(sourceFile, newStatements)\n\nconst result = printer.printFile(newSourceFile)\n\nwriteFileSync(kyselyTSPath, result, 'utf8')\n"
  },
  {
    "path": "scripts/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig-base.json\",\n  \"compilerOptions\": {\n    \"allowSyntheticDefaultImports\": true,\n    \"module\": \"ESNext\",\n    \"resolveJsonModule\": true\n  },\n  \"include\": [\"./\"]\n}\n"
  },
  {
    "path": "scripts/util/for-each-file.js",
    "content": "const fs = require('fs')\nconst path = require('path')\n\nfunction forEachFile(dir, callback) {\n  const files = fs.readdirSync(dir).filter((it) => it !== '.' && it !== '..')\n\n  for (const file of files) {\n    const filePath = path.join(dir, file)\n\n    if (isDir(filePath)) {\n      forEachFile(filePath, callback)\n    } else {\n      callback(filePath)\n    }\n  }\n}\n\nfunction isDir(file) {\n  return fs.lstatSync(file).isDirectory()\n}\n\nmodule.exports = forEachFile\n"
  },
  {
    "path": "site/.gitignore",
    "content": "# Dependencies\n/node_modules\n\n# Production\n/build\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# Misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n.vercel\n"
  },
  {
    "path": "site/babel.config.js",
    "content": "module.exports = {\n  presets: [require.resolve('@docusaurus/core/lib/babel/preset')],\n}\n"
  },
  {
    "path": "site/docs/dialects.md",
    "content": "# Dialects\n\nA dialect is the glue between Kysely and the underlying database engine. Check the [API docs](https://kysely-org.github.io/kysely-apidoc/interfaces/Dialect.html) to learn how to build your own.\n\n## Core dialects\n\n| Dialect | Link |\n| --- | --- |\n| PostgreSQL | https://kysely-org.github.io/kysely-apidoc/classes/PostgresDialect.html |\n| MySQL | https://kysely-org.github.io/kysely-apidoc/classes/MysqlDialect.html |\n| Microsoft SQL Server (MSSQL) | https://kysely-org.github.io/kysely-apidoc/classes/MssqlDialect.html |\n| SQLite | https://kysely-org.github.io/kysely-apidoc/classes/SqliteDialect.html |\n\n## Organization dialects\n\n| Dialect | Link |\n| --- | --- |\n| Postgres.js | https://github.com/kysely-org/kysely-postgres-js |\n| SingleStore Data API | https://github.com/kysely-org/kysely-singlestore |\n\n## Community dialects\n\n| Dialect                       | Link                                                                        |\n|-------------------------------|-----------------------------------------------------------------------------|\n| PlanetScale Serverless Driver | https://github.com/depot/kysely-planetscale                                 |\n| Cloudflare D1                 | https://github.com/aidenwallis/kysely-d1                                    |\n| Cloudflare Durable Objects    | https://github.com/benallfree/kysely-do                                     |\n| AWS RDS Data API              | https://github.com/serverless-stack/kysely-data-api                         |\n| SurrealDB                     | https://github.com/igalklebanov/kysely-surrealdb                            |\n| Neon                          | https://github.com/seveibar/kysely-neon                                     |\n| Xata                          | https://github.com/xataio/client-ts/tree/main/packages/plugin-client-kysely |\n| AWS S3 Select                 | https://github.com/igalklebanov/kysely-s3-select                            |\n| libSQL/sqld                   | https://github.com/libsql/kysely-libsql                                     |\n| Fetch driver                  | https://github.com/andersgee/kysely-fetch-driver                            |\n| SQLite WASM                   | https://github.com/DallasHoff/sqlocal                                       |\n| Deno SQLite                   | https://gitlab.com/soapbox-pub/kysely-deno-sqlite                           |\n| Node SQLite                   | https://github.com/wolfie/kysely-node-native-sqlite                         |\n| TiDB Cloud Serverless Driver  | https://github.com/tidbcloud/kysely                                         |\n| Capacitor SQLite Kysely       | https://github.com/DawidWetzler/capacitor-sqlite-kysely                     |\n| BigQuery                      | https://github.com/maktouch/kysely-bigquery                                 |\n| Clickhouse                    | https://github.com/founderpathcom/kysely-clickhouse                         |\n| PGLite                        | https://github.com/czeidler/kysely-pglite-dialect                           |\n| Oracle                        | https://github.com/griffiths-waite/kysely-oracledb                          |\n| Firebird                      | https://github.com/benkoppe/kysely-firebird                                 |\n| MariaDB                       | https://github.com/awaludinar/kysely-mariadb                                |\n"
  },
  {
    "path": "site/docs/examples/_category_.json",
    "content": "{\n  \"label\": \"Examples\",\n  \"position\": 5,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of how to use Kysely to achieve common tasks.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/examples/cte/0010-simple-selects.js",
    "content": "export const simpleSelects = `const result = await db\n  // Create a CTE called \\`jennifers\\` that selects all\n  // persons named 'Jennifer'.\n  .with('jennifers', (db) => db\n    .selectFrom('person')\n    .where('first_name', '=', 'Jennifer')\n    .select(['id', 'age'])\n  )\n  // Select all rows from the \\`jennifers\\` CTE and\n  // further filter it.\n  .with('adult_jennifers', (db) => db\n    .selectFrom('jennifers')\n    .where('age', '>', 18)\n    .select(['id', 'age'])\n  )\n  // Finally select all adult jennifers that are\n  // also younger than 60.\n  .selectFrom('adult_jennifers')\n  .where('age', '<', 60)\n  .selectAll()\n  .execute()`"
  },
  {
    "path": "site/docs/examples/cte/0010-simple-selects.mdx",
    "content": "---\ntitle: 'Simple selects'\n---\n\n# Simple selects\n\nCommon table expressions (CTE) are a great way to modularize complex queries.\nEssentially they allow you to run multiple separate queries within a\nsingle roundtrip to the DB.\n\nSince CTEs are a part of the main query, query optimizers inside DB\nengines are able to optimize the overall query. For example, postgres\nis able to inline the CTEs inside the using queries if it decides it's\nfaster.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  simpleSelects\n} from './0010-simple-selects'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={simpleSelects} />\n</div>\n"
  },
  {
    "path": "site/docs/examples/cte/0020-inserts-updates-and-deletions.js",
    "content": "export const insertsUpdatesAndDeletions = `const result = await db\n  .with('new_person', (db) => db\n    .insertInto('person')\n    .values({\n      first_name: 'Jennifer',\n      age: 35,\n    })\n    .returning('id')\n  )\n  .with('new_pet', (db) => db\n    .insertInto('pet')\n    .values({\n      name: 'Doggo',\n      species: 'dog',\n      is_favorite: true,\n      // Use the id of the person we just inserted.\n      owner_id: db\n        .selectFrom('new_person')\n        .select('id')\n    })\n    .returning('id')\n  )\n  .selectFrom(['new_person', 'new_pet'])\n  .select([\n    'new_person.id as person_id',\n    'new_pet.id as pet_id'\n  ])\n  .execute()`"
  },
  {
    "path": "site/docs/examples/cte/0020-inserts-updates-and-deletions.mdx",
    "content": "---\ntitle: 'Inserts, updates and deletions'\n---\n\n# Inserts, updates and deletions\n\nSome databases like postgres also allow you to run other queries than selects\nin CTEs. On these databases CTEs are extremely powerful:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  insertsUpdatesAndDeletions\n} from './0020-inserts-updates-and-deletions'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={insertsUpdatesAndDeletions} />\n</div>\n"
  },
  {
    "path": "site/docs/examples/cte/_category_.json",
    "content": "{\n  \"label\": \"CTE\",\n  \"position\": 9,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of how to use Common Table Expressions (CTE) in queries.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/examples/delete/0010-single-row.js",
    "content": "export const singleRow = `const result = await db\n  .deleteFrom('person')\n  .where('person.id', '=', 1)\n  .executeTakeFirst()\n\nconsole.log(result.numDeletedRows)`"
  },
  {
    "path": "site/docs/examples/delete/0010-single-row.mdx",
    "content": "---\ntitle: 'Single row'\n---\n\n# Single row\n\nDelete a single row:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  singleRow\n} from './0010-single-row'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={singleRow} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [deleteFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#deleteFrom)\n - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/DeleteQueryBuilder.html#returning)\n:::\n"
  },
  {
    "path": "site/docs/examples/delete/_category_.json",
    "content": "{\n  \"label\": \"DELETE\",\n  \"position\": 6,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of how to write DELETE queries.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/examples/insert/0010-single-row.js",
    "content": "export const singleRow = `const result = await db\n  .insertInto('person')\n  .values({\n    first_name: 'Jennifer',\n    last_name: 'Aniston',\n    age: 40\n  })\n  .executeTakeFirst()\n\n// \\`insertId\\` is only available on dialects that\n// automatically return the id of the inserted row\n// such as MySQL and SQLite. On PostgreSQL, for example,\n// you need to add a \\`returning\\` clause to the query to\n// get anything out. See the \"returning data\" example.\nconsole.log(result.insertId)`"
  },
  {
    "path": "site/docs/examples/insert/0010-single-row.mdx",
    "content": "---\ntitle: 'Single row'\n---\n\n# Single row\n\nInsert a single row:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  singleRow\n} from './0010-single-row'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={singleRow} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values)\n - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict)\n - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning)\n - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto)\n:::\n"
  },
  {
    "path": "site/docs/examples/insert/0020-multiple-rows.js",
    "content": "export const multipleRows = `await db\n  .insertInto('person')\n  .values([{\n    first_name: 'Jennifer',\n    last_name: 'Aniston',\n    age: 40,\n  }, {\n    first_name: 'Arnold',\n    last_name: 'Schwarzenegger',\n    age: 70,\n  }])\n  .execute()`"
  },
  {
    "path": "site/docs/examples/insert/0020-multiple-rows.mdx",
    "content": "---\ntitle: 'Multiple rows'\n---\n\n# Multiple rows\n\nOn dialects that support it (for example PostgreSQL) you can insert multiple\nrows by providing an array. Note that the return value is once again very\ndialect-specific. Some databases may only return the id of the *last* inserted\nrow and some return nothing at all unless you call `returning`.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  multipleRows\n} from './0020-multiple-rows'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={multipleRows} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values)\n - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict)\n - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning)\n - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto)\n:::\n"
  },
  {
    "path": "site/docs/examples/insert/0030-returning-data.js",
    "content": "export const returningData = `const result = await db\n  .insertInto('person')\n  .values({\n    first_name: 'Jennifer',\n    last_name: 'Aniston',\n    age: 40,\n  })\n  .returning(['id', 'first_name as name'])\n  .executeTakeFirstOrThrow()`"
  },
  {
    "path": "site/docs/examples/insert/0030-returning-data.mdx",
    "content": "---\ntitle: 'Returning data'\n---\n\n# Returning data\n\nOn supported dialects like PostgreSQL you need to chain `returning` to the query to get\nthe inserted row's columns (or any other expression) as the return value. `returning`\nworks just like `select`. Refer to `select` method's examples and documentation for\nmore info.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  returningData\n} from './0030-returning-data'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={returningData} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values)\n - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict)\n - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning)\n - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto)\n:::\n"
  },
  {
    "path": "site/docs/examples/insert/0040-complex-values.js",
    "content": "export const complexValues = `import { sql } from 'kysely'\n\nconst ani = \"Ani\"\nconst ston = \"ston\"\n\nconst result = await db\n  .insertInto('person')\n  .values(({ ref, selectFrom, fn }) => ({\n    first_name: 'Jennifer',\n    last_name: sql<string>\\`concat(\\${ani}, \\${ston})\\`,\n    middle_name: ref('first_name'),\n    age: selectFrom('person')\n      .select(fn.avg<number>('age').as('avg_age')),\n  }))\n  .executeTakeFirst()`"
  },
  {
    "path": "site/docs/examples/insert/0040-complex-values.mdx",
    "content": "---\ntitle: 'Complex values'\n---\n\n# Complex values\n\nIn addition to primitives, the values can also be arbitrary expressions.\nYou can build the expressions by using a callback and calling the methods\non the expression builder passed to it:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  complexValues\n} from './0040-complex-values'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={complexValues} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values)\n - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict)\n - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning)\n - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto)\n:::\n"
  },
  {
    "path": "site/docs/examples/insert/0050-insert-subquery.js",
    "content": "export const insertSubquery = `const result = await db.insertInto('person')\n  .columns(['first_name', 'last_name', 'age'])\n  .expression((eb) => eb\n    .selectFrom('pet')\n    .select((eb) => [\n      'pet.name',\n      eb.val('Petson').as('last_name'),\n      eb.lit(7).as('age'),\n    ])\n  )\n  .execute()`"
  },
  {
    "path": "site/docs/examples/insert/0050-insert-subquery.mdx",
    "content": "---\ntitle: 'Insert subquery'\n---\n\n# Insert subquery\n\nYou can create an `INSERT INTO SELECT FROM` query using the `expression` method.\nThis API doesn't follow our WYSIWYG principles and might be a bit difficult to\nremember. The reasons for this design stem from implementation difficulties.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  insertSubquery\n} from './0050-insert-subquery'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={insertSubquery} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values)\n - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict)\n - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning)\n - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto)\n:::\n"
  },
  {
    "path": "site/docs/examples/insert/_category_.json",
    "content": "{\n  \"label\": \"INSERT\",\n  \"position\": 4,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of how to write INSERT queries.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/examples/join/0010-simple-inner-join.js",
    "content": "export const simpleInnerJoin = `const result = await db\n  .selectFrom('person')\n  .innerJoin('pet', 'pet.owner_id', 'person.id')\n  // \\`select\\` needs to come after the call to \\`innerJoin\\` so\n  // that you can select from the joined table.\n  .select(['person.id', 'pet.name as pet_name'])\n  .execute()`"
  },
  {
    "path": "site/docs/examples/join/0010-simple-inner-join.mdx",
    "content": "---\ntitle: 'Simple inner join'\n---\n\n# Simple inner join\n\nSimple `inner join`s can be done by providing a table name and two columns to join:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  simpleInnerJoin\n} from './0010-simple-inner-join'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={simpleInnerJoin} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [innerJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin)\n - [leftJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin)\n - [rightJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin)\n - [fullJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin)\n:::\n"
  },
  {
    "path": "site/docs/examples/join/0020-aliased-inner-join.js",
    "content": "export const aliasedInnerJoin = `await db.selectFrom('person')\n  .innerJoin('pet as p', 'p.owner_id', 'person.id')\n  .where('p.name', '=', 'Doggo')\n  .selectAll()\n  .execute()`"
  },
  {
    "path": "site/docs/examples/join/0020-aliased-inner-join.mdx",
    "content": "---\ntitle: 'Aliased inner join'\n---\n\n# Aliased inner join\n\nYou can give an alias for the joined table like this:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  aliasedInnerJoin\n} from './0020-aliased-inner-join'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={aliasedInnerJoin} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [innerJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin)\n - [leftJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin)\n - [rightJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin)\n - [fullJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin)\n:::\n"
  },
  {
    "path": "site/docs/examples/join/0030-complex-join.js",
    "content": "export const complexJoin = `await db.selectFrom('person')\n  .innerJoin(\n    'pet',\n    (join) => join\n      .onRef('pet.owner_id', '=', 'person.id')\n      .on('pet.name', '=', 'Doggo')\n      .on((eb) => eb.or([\n        eb('person.age', '>', 18),\n        eb('person.age', '<', 100)\n      ]))\n  )\n  .selectAll()\n  .execute()`"
  },
  {
    "path": "site/docs/examples/join/0030-complex-join.mdx",
    "content": "---\ntitle: 'Complex join'\n---\n\n# Complex join\n\nYou can provide a function as the second argument to get a join\nbuilder for creating more complex joins. The join builder has a\nbunch of `on*` methods for building the `on` clause of the join.\nThere's basically an equivalent for every `where` method\n(`on`, `onRef` etc.).\n\nYou can do all the same things with the\n`on` method that you can with the corresponding `where` method (like [OR expressions for example](https://kysely.dev/docs/examples/WHERE/or-where)).\nSee the `where` method documentation for more examples.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  complexJoin\n} from './0030-complex-join'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={complexJoin} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [innerJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin)\n - [leftJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin)\n - [rightJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin)\n - [fullJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin)\n:::\n"
  },
  {
    "path": "site/docs/examples/join/0040-subquery-join.js",
    "content": "export const subqueryJoin = `const result = await db.selectFrom('person')\n  .innerJoin(\n    (eb) => eb\n      .selectFrom('pet')\n      .select(['owner_id as owner', 'name'])\n      .where('name', '=', 'Doggo')\n      .as('doggos'),\n    (join) => join\n      .onRef('doggos.owner', '=', 'person.id'),\n  )\n  .selectAll('doggos')\n  .execute()`"
  },
  {
    "path": "site/docs/examples/join/0040-subquery-join.mdx",
    "content": "---\ntitle: 'Subquery join'\n---\n\n# Subquery join\n\nYou can join a subquery by providing two callbacks:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  subqueryJoin\n} from './0040-subquery-join'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={subqueryJoin} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [innerJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin)\n - [leftJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin)\n - [rightJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin)\n - [fullJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin)\n:::\n"
  },
  {
    "path": "site/docs/examples/join/_category_.json",
    "content": "{\n  \"label\": \"JOIN\",\n  \"position\": 3,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Examples of queries that use JOINs.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/examples/merge/0010-source-row-existence.js",
    "content": "export const sourceRowExistence = `const result = await db\n  .mergeInto('person as target')\n  .using('pet as source', 'source.owner_id', 'target.id')\n  .whenMatchedAnd('target.has_pets', '!=', 'Y')\n  .thenUpdateSet({ has_pets: 'Y' })\n  .whenNotMatchedBySourceAnd('target.has_pets', '=', 'Y')\n  .thenUpdateSet({ has_pets: 'N' })\n  .executeTakeFirstOrThrow()\n\nconsole.log(result.numChangedRows)`"
  },
  {
    "path": "site/docs/examples/merge/0010-source-row-existence.mdx",
    "content": "---\ntitle: 'Source row existence'\n---\n\n# Source row existence\n\nUpdate a target column based on the existence of a source row:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  sourceRowExistence\n} from './0010-source-row-existence'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={sourceRowExistence} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [mergeInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#mergeInto)\n - [using method](https://kysely-org.github.io/kysely-apidoc/classes/MergeQueryBuilder.html#using)\n - [whenMatched method](https://kysely-org.github.io/kysely-apidoc/classes/WheneableMergeQueryBuilder.html#whenMatched)\n - [thenUpdateSet method](https://kysely-org.github.io/kysely-apidoc/classes/MatchedThenableMergeQueryBuilder.html#thenUpdateSet)\n - [thenDelete method](https://kysely-org.github.io/kysely-apidoc/classes/MatchedThenableMergeQueryBuilder.html#thenDelete)\n - [thenDoNothing method](https://kysely-org.github.io/kysely-apidoc/classes/MatchedThenableMergeQueryBuilder.html#thenDoNothing)\n - [whenNotMatched method](https://kysely-org.github.io/kysely-apidoc/classes/WheneableMergeQueryBuilder.html#whenNotMatched)\n - [thenInsertValues method](https://kysely-org.github.io/kysely-apidoc/classes/NotMatchedThenableMergeQueryBuilder.html#thenInsertValues)\n:::\n"
  },
  {
    "path": "site/docs/examples/merge/0020-temporary-changes-table.js",
    "content": "export const temporaryChangesTable = `const result = await db\n  .mergeInto('wine as target')\n  .using(\n    'wine_stock_change as source',\n    'source.wine_name',\n    'target.name',\n  )\n  .whenNotMatchedAnd('source.stock_delta', '>', 0)\n  .thenInsertValues(({ ref }) => ({\n    name: ref('source.wine_name'),\n    stock: ref('source.stock_delta'),\n  }))\n  .whenMatchedAnd(\n    (eb) => eb('target.stock', '+', eb.ref('source.stock_delta')),\n    '>',\n    0,\n  )\n  .thenUpdateSet('stock', (eb) =>\n    eb('target.stock', '+', eb.ref('source.stock_delta')),\n  )\n  .whenMatched()\n  .thenDelete()\n  .executeTakeFirstOrThrow()`"
  },
  {
    "path": "site/docs/examples/merge/0020-temporary-changes-table.mdx",
    "content": "---\ntitle: 'Temporary changes table'\n---\n\n# Temporary changes table\n\nMerge new entries from a temporary changes table:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  temporaryChangesTable\n} from './0020-temporary-changes-table'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={temporaryChangesTable} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [mergeInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#mergeInto)\n - [using method](https://kysely-org.github.io/kysely-apidoc/classes/MergeQueryBuilder.html#using)\n - [whenMatched method](https://kysely-org.github.io/kysely-apidoc/classes/WheneableMergeQueryBuilder.html#whenMatched)\n - [thenUpdateSet method](https://kysely-org.github.io/kysely-apidoc/classes/MatchedThenableMergeQueryBuilder.html#thenUpdateSet)\n - [thenDelete method](https://kysely-org.github.io/kysely-apidoc/classes/MatchedThenableMergeQueryBuilder.html#thenDelete)\n - [thenDoNothing method](https://kysely-org.github.io/kysely-apidoc/classes/MatchedThenableMergeQueryBuilder.html#thenDoNothing)\n - [whenNotMatched method](https://kysely-org.github.io/kysely-apidoc/classes/WheneableMergeQueryBuilder.html#whenNotMatched)\n - [thenInsertValues method](https://kysely-org.github.io/kysely-apidoc/classes/NotMatchedThenableMergeQueryBuilder.html#thenInsertValues)\n:::\n"
  },
  {
    "path": "site/docs/examples/merge/_category_.json",
    "content": "{\n  \"label\": \"MERGE\",\n  \"position\": 7,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of how to write MERGE queries.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/examples/select/0010-a-single-column.js",
    "content": "export const aSingleColumn = `const persons = await db\n  .selectFrom('person')\n  .select('id')\n  .where('first_name', '=', 'Arnold')\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0010-a-single-column.mdx",
    "content": "---\ntitle: 'A single column'\n---\n\n# A single column\n\nSelect a single column:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  aSingleColumn\n} from './0010-a-single-column'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={aSingleColumn} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0020-column-with-a-table.js",
    "content": "export const columnWithATable = `const persons = await db\n  .selectFrom(['person', 'pet'])\n  .select('person.id')\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0020-column-with-a-table.mdx",
    "content": "---\ntitle: 'Column with a table'\n---\n\n# Column with a table\n\nSelect a single column and specify a table:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  columnWithATable\n} from './0020-column-with-a-table'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={columnWithATable} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0030-multiple-columns.js",
    "content": "export const multipleColumns = `const persons = await db\n  .selectFrom('person')\n  .select(['person.id', 'first_name'])\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0030-multiple-columns.mdx",
    "content": "---\ntitle: 'Multiple columns'\n---\n\n# Multiple columns\n\nSelect multiple columns:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  multipleColumns\n} from './0030-multiple-columns'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={multipleColumns} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0040-aliases.js",
    "content": "export const aliases = `const persons = await db\n  .selectFrom('person as p')\n  .select([\n    'first_name as fn',\n    'p.last_name as ln'\n  ])\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0040-aliases.mdx",
    "content": "---\ntitle: 'Aliases'\n---\n\n# Aliases\n\nYou can give an alias for selections and tables by appending `as the_alias` to the name:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  aliases\n} from './0040-aliases'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={aliases} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0050-complex-selections.js",
    "content": "export const complexSelections = `import { sql } from 'kysely'\n\nconst persons = await db.selectFrom('person')\n  .select(({ eb, selectFrom, or, val, lit }) => [\n    // Select a correlated subquery\n    selectFrom('pet')\n      .whereRef('person.id', '=', 'pet.owner_id')\n      .select('pet.name')\n      .orderBy('pet.name')\n      .limit(1)\n      .as('first_pet_name'),\n\n    // Build and select an expression using\n    // the expression builder\n    or([\n      eb('first_name', '=', 'Jennifer'),\n      eb('first_name', '=', 'Arnold')\n    ]).as('is_jennifer_or_arnold'),\n\n    // Select a raw sql expression\n    sql<string>\\`concat(first_name, ' ', last_name)\\`.as('full_name'),\n\n    // Select a static string value\n    val('Some value').as('string_value'),\n\n    // Select a literal value\n    lit(42).as('literal_value'),\n  ])\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0050-complex-selections.mdx",
    "content": "---\ntitle: 'Complex selections'\n---\n\n# Complex selections\n\nYou can select arbitrary expression including subqueries and raw sql snippets.\nWhen you do that, you need to give a name for the selections using the `as` method:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  complexSelections\n} from './0050-complex-selections'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={complexSelections} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0051-not-null.js",
    "content": "export const notNull = `import { NotNull } from 'kysely'\nimport { jsonObjectFrom } from 'kysely/helpers/postgres'\n\nconst persons = db\n  .selectFrom('person')\n  .select((eb) => [\n    'last_name',\n     // Let's assume we know the person has at least one\n     // pet. We can use the \\`.$notNull()\\` method to make\n     // the expression not null. You could just as well\n     // add \\`pet\\` to the \\`$narrowType\\` call below.\n     jsonObjectFrom(\n       eb.selectFrom('pet')\n         .selectAll()\n         .limit(1)\n         .whereRef('person.id', '=', 'pet.owner_id')\n     ).$notNull().as('pet')\n  ])\n  .where('last_name', 'is not', null)\n  // $narrowType can be used to narrow the output type.\n  // The special \\`NotNull\\` type can be used to make a\n  // selection not null. You could add \\`pet: NotNull\\`\n  // here and omit the \\`$notNull()\\` call on it.\n  // Use whichever way you prefer.\n  .$narrowType<{ last_name: NotNull }>()\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0051-not-null.mdx",
    "content": "---\ntitle: 'Not null'\n---\n\n# Not null\n\nSometimes you can be sure something's not null, but Kysely isn't able to infer\nit. For example calling `where('last_name', 'is not', null)` doesn't make\n`last_name` not null in the result type, but unless you have other where statements\nyou can be sure it's never null.\n\nKysely has a couple of helpers for dealing with these cases: `$notNull()` and `$narrowType`.\nBoth are used in the following example:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  notNull\n} from './0051-not-null'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={notNull} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0060-function-calls.js",
    "content": "export const functionCalls = `import { sql } from 'kysely'\n\nconst result = await db.selectFrom('person')\n  .innerJoin('pet', 'pet.owner_id', 'person.id')\n  .select(({ fn, val, ref }) => [\n    'person.id',\n\n    // The \\`fn\\` module contains the most common\n    // functions.\n    fn.count<number>('pet.id').as('pet_count'),\n\n    // You can call any function by calling \\`fn\\`\n    // directly. The arguments are treated as column\n    // references by default. If you want  to pass in\n    // values, use the \\`val\\` function.\n    fn<string>('concat', [\n      val('Ms. '),\n      'first_name',\n      val(' '),\n      'last_name'\n    ]).as('full_name_with_title'),\n\n    // You can call any aggregate function using the\n    // \\`fn.agg\\` function.\n    fn.agg<string[]>('array_agg', ['pet.name']).as('pet_names'),\n\n    // And once again, you can use the \\`sql\\`\n    // template tag. The template tag substitutions\n    // are treated as values by default. If you want\n    // to reference columns, you can use the \\`ref\\`\n    // function.\n    sql<string>\\`concat(\n      \\${ref('first_name')},\n      ' ',\n      \\${ref('last_name')}\n    )\\`.as('full_name')\n  ])\n  .groupBy('person.id')\n  .having((eb) => eb.fn.count('pet.id'), '>', 10)\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0060-function-calls.mdx",
    "content": "---\ntitle: 'Function calls'\n---\n\n# Function calls\n\nThis example shows how to create function calls. These examples also work in any\nother place (`where` calls, updates, inserts etc.). The only difference is that you\nleave out the alias (the `as` call) if you use these in any other place than `select`.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  functionCalls\n} from './0060-function-calls'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={functionCalls} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0070-distinct.js",
    "content": "export const distinct = `const persons = await db.selectFrom('person')\n  .select('first_name')\n  .distinct()\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0070-distinct.mdx",
    "content": "---\ntitle: 'Distinct'\n---\n\n# Distinct\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  distinct\n} from './0070-distinct'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={distinct} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0080-distinct-on.js",
    "content": "export const distinctOn = `const persons = await db.selectFrom('person')\n  .innerJoin('pet', 'pet.owner_id', 'person.id')\n  .where('pet.name', '=', 'Doggo')\n  .distinctOn('person.id')\n  .selectAll('person')\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0080-distinct-on.mdx",
    "content": "---\ntitle: 'Distinct on'\n---\n\n# Distinct on\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  distinctOn\n} from './0080-distinct-on'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={distinctOn} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0090-all-columns.js",
    "content": "export const allColumns = `const persons = await db\n  .selectFrom('person')\n  .selectAll()\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0090-all-columns.mdx",
    "content": "---\ntitle: 'All columns'\n---\n\n# All columns\n\nThe `selectAll` method generates `SELECT *`:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  allColumns\n} from './0090-all-columns'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={allColumns} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0100-all-columns-of-a-table.js",
    "content": "export const allColumnsOfATable = `const persons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0100-all-columns-of-a-table.mdx",
    "content": "---\ntitle: 'All columns of a table'\n---\n\n# All columns of a table\n\nSelect all columns of a table:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  allColumnsOfATable\n} from './0100-all-columns-of-a-table'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={allColumnsOfATable} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0110-nested-array.js",
    "content": "export const nestedArray = `import { jsonArrayFrom } from 'kysely/helpers/postgres'\n\nconst result = await db\n  .selectFrom('person')\n  .select((eb) => [\n    'id',\n    jsonArrayFrom(\n      eb.selectFrom('pet')\n        .select(['pet.id as pet_id', 'pet.name'])\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .orderBy('pet.name')\n    ).as('pets')\n  ])\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0110-nested-array.mdx",
    "content": "---\ntitle: 'Nested array'\n---\n\n# Nested array\n\nWhile kysely is not an ORM and it doesn't have the concept of relations, we do provide\nhelpers for fetching nested objects and arrays in a single query. In this example we\nuse the `jsonArrayFrom` helper to fetch person's pets along with the person's id.\n\nPlease keep in mind that the helpers under the `kysely/helpers` folder, including\n`jsonArrayFrom`, are not guaranteed to work with third party dialects. In order for\nthem to work, the dialect must automatically parse the `json` data type into\nJavaScript JSON values like objects and arrays. Some dialects might simply return\nthe data as a JSON string. In these cases you can use the built in `ParseJSONResultsPlugin`\nto parse the results.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  nestedArray\n} from './0110-nested-array'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={nestedArray} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0120-nested-object.js",
    "content": "export const nestedObject = `import { jsonObjectFrom } from 'kysely/helpers/postgres'\n\nconst result = await db\n  .selectFrom('person')\n  .select((eb) => [\n    'id',\n    jsonObjectFrom(\n      eb.selectFrom('pet')\n        .select(['pet.id as pet_id', 'pet.name'])\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .where('pet.is_favorite', '=', true)\n    ).as('favorite_pet')\n  ])\n  .execute()`"
  },
  {
    "path": "site/docs/examples/select/0120-nested-object.mdx",
    "content": "---\ntitle: 'Nested object'\n---\n\n# Nested object\n\nWhile kysely is not an ORM and it doesn't have the concept of relations, we do provide\nhelpers for fetching nested objects and arrays in a single query. In this example we\nuse the `jsonObjectFrom` helper to fetch person's favorite pet along with the person's id.\n\nPlease keep in mind that the helpers under the `kysely/helpers` folder, including\n`jsonObjectFrom`, are not guaranteed to work with third-party dialects. In order for\nthem to work, the dialect must automatically parse the `json` data type into\nJavaScript JSON values like objects and arrays. Some dialects might simply return\nthe data as a JSON string. In these cases you can use the built in `ParseJSONResultsPlugin`\nto parse the results.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  nestedObject\n} from './0120-nested-object'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={nestedObject} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/0130-generic-find-query.js",
    "content": "export const genericFindQuery = `import { SelectType } from 'kysely'\nimport { Database } from 'type-editor'\n\nasync function getRowByColumn<\n  T extends keyof Database,\n  C extends keyof Database[T] & string,\n  V extends SelectType<Database[T][C]>,\n>(t: T, c: C, v: V) {\n  // We need to use the dynamic module since the table name\n  // is not known at compile time.\n  const { table, ref } = db.dynamic\n\n  return await db\n    .selectFrom(table(t).as('t'))\n    .selectAll()\n    .where(ref(c), '=', v)\n    .orderBy('t.id')\n    .executeTakeFirstOrThrow()\n}\n\nconst person = await getRowByColumn('person', 'first_name', 'Arnold')`"
  },
  {
    "path": "site/docs/examples/select/0130-generic-find-query.mdx",
    "content": "---\ntitle: 'Generic find query'\n---\n\n# Generic find query\n\nA generic type-safe helper function for finding a row by a column value:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  genericFindQuery\n} from './0130-generic-find-query'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={genericFindQuery} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)\n - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)\n - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)\n:::\n"
  },
  {
    "path": "site/docs/examples/select/_category_.json",
    "content": "{\n  \"label\": \"SELECT\",\n  \"position\": 1,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of using the SELECT methods.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/examples/transactions/0010-simple-transaction.js",
    "content": "export const simpleTransaction = `const catto = await db.transaction().execute(async (trx) => {\n  const jennifer = await trx.insertInto('person')\n    .values({\n      first_name: 'Jennifer',\n      last_name: 'Aniston',\n      age: 40,\n    })\n    .returning('id')\n    .executeTakeFirstOrThrow()\n\n  return await trx.insertInto('pet')\n    .values({\n      owner_id: jennifer.id,\n      name: 'Catto',\n      species: 'cat',\n      is_favorite: false,\n    })\n    .returningAll()\n    .executeTakeFirst()\n})`"
  },
  {
    "path": "site/docs/examples/transactions/0010-simple-transaction.mdx",
    "content": "---\ntitle: 'Simple transaction'\n---\n\n# Simple transaction\n\nThis example inserts two rows in a transaction. If an exception is thrown inside\nthe callback passed to the `execute` method,\n1. the exception is caught,\n2. the transaction is rolled back, and\n3. the exception is thrown again.\nOtherwise the transaction is committed.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  simpleTransaction\n} from './0010-simple-transaction'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={simpleTransaction} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [transaction method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#transaction)\n:::\n"
  },
  {
    "path": "site/docs/examples/transactions/0011-controlled-transaction.js",
    "content": "export const controlledTransaction = `const trx = await db.startTransaction().execute()\n\ntry {\n  const jennifer = await trx.insertInto('person')\n    .values({\n      first_name: 'Jennifer',\n      last_name: 'Aniston',\n      age: 40,\n    })\n    .returning('id')\n    .executeTakeFirstOrThrow()\n\n  const catto = await trx.insertInto('pet')\n    .values({\n      owner_id: jennifer.id,\n      name: 'Catto',\n      species: 'cat',\n      is_favorite: false,\n    })\n    .returningAll()\n    .executeTakeFirstOrThrow()\n\n  await trx.commit().execute()\n\n  // ...\n} catch (error) {\n  await trx.rollback().execute()\n}`"
  },
  {
    "path": "site/docs/examples/transactions/0011-controlled-transaction.mdx",
    "content": "---\ntitle: 'Controlled transaction'\n---\n\n# Controlled transaction\n\nA controlled transaction allows you to commit and rollback manually, execute\nsavepoint commands, and queries in general.\n\nIn this example we start a transaction, use it to insert two rows and then commit\nthe transaction. If an error is thrown, we catch it and rollback the transaction.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  controlledTransaction\n} from './0011-controlled-transaction'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={controlledTransaction} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [transaction method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#transaction)\n:::\n"
  },
  {
    "path": "site/docs/examples/transactions/0012-controlled-transaction-w-savepoints.js",
    "content": "export const controlledTransactionWSavepoints = `const trx = await db.startTransaction().execute()\n\ntry {\n  const jennifer = await trx\n    .insertInto('person')\n    .values({\n      first_name: 'Jennifer',\n      last_name: 'Aniston',\n      age: 40,\n    })\n    .returning('id')\n    .executeTakeFirstOrThrow()\n\n  const trxAfterJennifer = await trx.savepoint('after_jennifer').execute()\n\n  try {\n    const catto = await trxAfterJennifer\n      .insertInto('pet')\n      .values({\n        owner_id: jennifer.id,\n        name: 'Catto',\n        species: 'cat',\n      })\n      .returning('id')\n      .executeTakeFirstOrThrow()\n\n    await trxAfterJennifer\n      .insertInto('toy')\n      .values({ name: 'Bone', price: 1.99, pet_id: catto.id })\n      .execute()\n  } catch (error) {\n    await trxAfterJennifer.rollbackToSavepoint('after_jennifer').execute()\n  }\n\n  await trxAfterJennifer.releaseSavepoint('after_jennifer').execute()\n\n  await trx.insertInto('audit').values({ action: 'added Jennifer' }).execute()\n\n  await trx.commit().execute()\n} catch (error) {\n  await trx.rollback().execute()\n}`"
  },
  {
    "path": "site/docs/examples/transactions/0012-controlled-transaction-w-savepoints.mdx",
    "content": "---\ntitle: 'Controlled transaction /w savepoints'\n---\n\n# Controlled transaction /w savepoints\n\nA controlled transaction allows you to commit and rollback manually, execute\nsavepoint commands, and queries in general.\n\nIn this example we start a transaction, insert a person, create a savepoint,\ntry inserting a toy and a pet, and if an error is thrown, we rollback to the\nsavepoint. Eventually we release the savepoint, insert an audit record and\ncommit the transaction. If an error is thrown, we catch it and rollback the\ntransaction.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  controlledTransactionWSavepoints\n} from './0012-controlled-transaction-w-savepoints'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={controlledTransactionWSavepoints} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [transaction method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#transaction)\n:::\n"
  },
  {
    "path": "site/docs/examples/transactions/_category_.json",
    "content": "{\n  \"label\": \"Transactions\",\n  \"position\": 8,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of how to use transactions.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/examples/update/0010-single-row.js",
    "content": "export const singleRow = `const result = await db\n  .updateTable('person')\n  .set({\n    first_name: 'Jennifer',\n    last_name: 'Aniston'\n  })\n  .where('id', '=', 1)\n  .executeTakeFirst()`"
  },
  {
    "path": "site/docs/examples/update/0010-single-row.mdx",
    "content": "---\ntitle: 'Single row'\n---\n\n# Single row\n\nUpdate a row in `person` table:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  singleRow\n} from './0010-single-row'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={singleRow} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [set method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#set)\n - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#returning)\n - [updateTable method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#updateTable)\n:::\n"
  },
  {
    "path": "site/docs/examples/update/0020-complex-values.js",
    "content": "export const complexValues = `const result = await db\n  .updateTable('person')\n  .set((eb) => ({\n    age: eb('age', '+', 1),\n    first_name: eb.selectFrom('pet').select('name').limit(1),\n    last_name: 'updated',\n  }))\n  .where('id', '=', 1)\n  .executeTakeFirst()`"
  },
  {
    "path": "site/docs/examples/update/0020-complex-values.mdx",
    "content": "---\ntitle: 'Complex values'\n---\n\n# Complex values\n\nAs always, you can provide a callback to the `set` method to get access\nto an expression builder:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  complexValues\n} from './0020-complex-values'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={complexValues} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [set method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#set)\n - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#returning)\n - [updateTable method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#updateTable)\n:::\n"
  },
  {
    "path": "site/docs/examples/update/0030-my-sql-joins.js",
    "content": "export const mySqlJoins = `const result = await db\n  .updateTable(['person', 'pet'])\n  .set('person.first_name', 'Updated person')\n  .set('pet.name', 'Updated doggo')\n  .whereRef('person.id', '=', 'pet.owner_id')\n  .where('person.id', '=', 1)\n  .executeTakeFirst()`"
  },
  {
    "path": "site/docs/examples/update/0030-my-sql-joins.mdx",
    "content": "---\ntitle: 'MySQL joins'\n---\n\n# MySQL joins\n\nMySQL allows you to join tables directly to the \"main\" table and update\nrows of all joined tables. This is possible by passing all tables to the\n`updateTable` method as a list and adding the `ON` conditions as `WHERE`\nstatements. You can then use the `set(column, value)` variant to update\ncolumns using table qualified names.\n\nThe `UpdateQueryBuilder` also has `innerJoin` etc. join methods, but those\ncan only be used as part of a PostgreSQL `update set from join` query.\nDue to type complexity issues, we unfortunately can't make the same\nmethods work in both cases.\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  mySqlJoins\n} from './0030-my-sql-joins'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={mySqlJoins} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [set method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#set)\n - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#returning)\n - [updateTable method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#updateTable)\n:::\n"
  },
  {
    "path": "site/docs/examples/update/_category_.json",
    "content": "{\n  \"label\": \"UPDATE\",\n  \"position\": 5,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of how to write UPDATE queries.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/examples/where/0010-simple-where-clause.js",
    "content": "export const simpleWhereClause = `const person = await db\n  .selectFrom('person')\n  .selectAll()\n  .where('first_name', '=', 'Jennifer')\n  .where('age', '>', 40)\n  .executeTakeFirst()`"
  },
  {
    "path": "site/docs/examples/where/0010-simple-where-clause.mdx",
    "content": "---\ntitle: 'Simple where clause'\n---\n\n# Simple where clause\n\n`where` method calls are combined with `AND`:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  simpleWhereClause\n} from './0010-simple-where-clause'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={simpleWhereClause} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)\n - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)\n:::\n"
  },
  {
    "path": "site/docs/examples/where/0020-where-in.js",
    "content": "export const whereIn = `const persons = await db\n  .selectFrom('person')\n  .selectAll()\n  .where('id', 'in', [1, 2, 3])\n  .execute()`"
  },
  {
    "path": "site/docs/examples/where/0020-where-in.mdx",
    "content": "---\ntitle: 'Where in'\n---\n\n# Where in\n\nFind multiple items using a list of identifiers:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  whereIn\n} from './0020-where-in'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={whereIn} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)\n - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)\n:::\n"
  },
  {
    "path": "site/docs/examples/where/0030-object-filter.js",
    "content": "export const objectFilter = `const persons = await db\n  .selectFrom('person')\n  .selectAll()\n  .where((eb) => eb.and({\n    first_name: 'Jennifer',\n    last_name: eb.ref('first_name')\n  }))\n  .execute()`"
  },
  {
    "path": "site/docs/examples/where/0030-object-filter.mdx",
    "content": "---\ntitle: 'Object filter'\n---\n\n# Object filter\n\nYou can use the `and` function to create a simple equality\nfilter using an object\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  objectFilter\n} from './0030-object-filter'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={objectFilter} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)\n - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)\n:::\n"
  },
  {
    "path": "site/docs/examples/where/0040-or-where.js",
    "content": "export const orWhere = `const persons = await db\n  .selectFrom('person')\n  .selectAll()\n  // 1. Using the \\`or\\` method on the expression builder:\n  .where((eb) => eb.or([\n    eb('first_name', '=', 'Jennifer'),\n    eb('first_name', '=', 'Sylvester')\n  ]))\n  // 2. Chaining expressions using the \\`or\\` method on the\n  // created expressions:\n  .where((eb) =>\n    eb('last_name', '=', 'Aniston').or('last_name', '=', 'Stallone')\n  )\n  .execute()`"
  },
  {
    "path": "site/docs/examples/where/0040-or-where.mdx",
    "content": "---\ntitle: 'OR where'\n---\n\n# OR where\n\nTo combine conditions using `OR`, you can use the expression builder.\nThere are two ways to create `OR` expressions. Both are shown in this\nexample:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  orWhere\n} from './0040-or-where'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={orWhere} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)\n - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)\n:::\n"
  },
  {
    "path": "site/docs/examples/where/0050-conditional-where-calls.js",
    "content": "export const conditionalWhereCalls = `import { Expression, SqlBool } from 'kysely'\n\nconst firstName: string | undefined = 'Jennifer'\nconst lastName: string | undefined = 'Aniston'\nconst under18 = true\nconst over60 = true\n\nlet query = db\n  .selectFrom('person')\n  .selectAll()\n\nif (firstName) {\n  // The query builder is immutable. Remember to reassign\n  // the result back to the query variable.\n  query = query.where('first_name', '=', firstName)\n}\n\nif (lastName) {\n  query = query.where('last_name', '=', lastName)\n}\n\nif (under18 || over60) {\n  // Conditional OR expressions can be added like this.\n  query = query.where((eb) => {\n    const ors: Expression<SqlBool>[] = []\n\n    if (under18) {\n      ors.push(eb('age', '<', 18))\n    }\n\n    if (over60) {\n      ors.push(eb('age', '>', 60))\n    }\n\n    return eb.or(ors)\n  })\n}\n\nconst persons = await query.execute()`"
  },
  {
    "path": "site/docs/examples/where/0050-conditional-where-calls.mdx",
    "content": "---\ntitle: 'Conditional where calls'\n---\n\n# Conditional where calls\n\nYou can add expressions conditionally like this:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  conditionalWhereCalls\n} from './0050-conditional-where-calls'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={conditionalWhereCalls} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)\n - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)\n:::\n"
  },
  {
    "path": "site/docs/examples/where/0060-complex-where-clause.js",
    "content": "export const complexWhereClause = `const firstName = 'Jennifer'\nconst maxAge = 60\n\nconst persons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .where(({ eb, or, and, not, exists, selectFrom }) => and([\n    or([\n      eb('first_name', '=', firstName),\n      eb('age', '<', maxAge)\n    ]),\n    not(exists(\n      selectFrom('pet')\n        .select('pet.id')\n        .whereRef('pet.owner_id', '=', 'person.id')\n    ))\n  ]))\n  .execute()`"
  },
  {
    "path": "site/docs/examples/where/0060-complex-where-clause.mdx",
    "content": "---\ntitle: 'Complex where clause'\n---\n\n# Complex where clause\n\nFor complex `where` expressions you can pass in a single callback and\nuse the `ExpressionBuilder` to build your expression:\n\nimport { Playground } from '../../../src/components/Playground'\n\nimport {\n  complexWhereClause\n} from './0060-complex-where-clause'\n\n<div style={{ marginBottom: '1em' }}>\n  <Playground code={complexWhereClause} />\n</div>\n\n:::info[More examples]\nThe API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),\nbut you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always\njust one hover away!\n\nFor example, check out these sections:\n - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)\n - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)\n:::\n"
  },
  {
    "path": "site/docs/examples/where/_category_.json",
    "content": "{\n  \"label\": \"WHERE\",\n  \"position\": 2,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Short and simple examples of how to use the where method to add a WHERE statement. While most of the examples show a SELECT query, the where method works exactly the same in UPDATE and DELETE queries too.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/execution.mdx",
    "content": "---\nsidebar_position: 3\ntitle: 'Execution flow'\n---\n\nThe following page gives a **simplified** overview of Kysely's execution flow, from query\nbuilding to querying the database. It is a nice introduction for anyone looking\nto understand how Kysely works under the hood. Knowing what your dependencies do\nand don't do is always a good idea!\n\nThis breakdown explains the journey from a type-safe method call in your application\nto receiving results from the database, as depicted in the diagram.\n\n1.  ### Immutable query building\n\n    The process starts in your `App`. You interact with the `QueryBuilder` by calling\n    its methods (`selectFrom`, `where`, etc.). Each call returns a _new_ `QueryBuilder`\n    instance containing an updated, immutable `QueryAST` (Abstract Syntax Tree),\n    which is the internal representation of your SQL query.\n\n    ```mermaid\n    sequenceDiagram\n        actor Y as App\n        participant QB as QueryBuilder\n\n        activate Y\n\n        loop more to build\n            Y->>+QB: method(type-safe inputs)\n            QB->>QB: QueryAST\n            QB-->>Y: new QueryBuilder\n        end\n\n        deactivate QB\n        deactivate Y\n    ```\n\n1.  ### Initiating execution\n\n    When you chain the final `.execute()` call, the `QueryBuilder` begins a multi-step\n    execution process, commanding the `QueryExecutor` to perform distinct tasks.\n\n    ```mermaid\n    sequenceDiagram\n        autonumber 4\n\n        actor Y as App\n        participant QB as QueryBuilder\n\n        activate Y\n\n        Y->>+QB: execute()\n\n        deactivate QB\n        deactivate Y\n    ```\n\n1.  ### Query Transformation\n\n    First, the `QueryBuilder` instructs the `QueryExecutor` to process the `QueryAST`.\n    The `QueryExecutor` iterates through all registered plugins, calling `transformQuery`\n    on each. This allows plugins to modify the query structure before compilation.\n    The final, transformed `QueryAST` is returned to the `QueryBuilder`.\n\n    ```mermaid\n    sequenceDiagram\n        autonumber 5\n\n        participant QB as QueryBuilder\n        participant QE as QueryExecutor\n        participant P as Plugin\n\n        activate QB\n\n        QB->>+QE: transformQuery(QueryAST)\n\n            loop all plugins\n                QE->>+P: transformQuery(QueryAST)\n                P-->>-QE: Transformed QueryAST\n            end\n\n        QE-->>-QB: Transformed QueryAST\n\n        deactivate QB\n    ```\n\n1.  ### Query Compilation\n\n    Next, the `QueryBuilder` tells the `QueryExecutor` to compile the transformed AST.\n    The `QueryExecutor` delegates this to the `Dialect`-specific `QueryCompiler`.\n    The compiler traverses the AST and produces a `CompiledQuery` object (containing\n    the final SQL string and parameters). This `CompiledQuery` is then returned\n    to the `QueryBuilder`.\n\n    ```mermaid\n    sequenceDiagram\n        autonumber 9\n\n        participant QB as QueryBuilder\n        participant QE as QueryExecutor\n\n        box Dialect\n            participant QC as QueryCompiler\n        end\n\n        activate QB\n\n        QB->>+QE: compileQuery(QueryAST)\n\n            QE->>+QC: compileQuery(QueryAST)\n            QC-->>-QE: CompiledQuery\n\n        QE-->>-QB: CompiledQuery\n\n        deactivate QB\n    ```\n\n1.  ### Execution & Connection Handling\n\n    The `QueryBuilder` now asks the `QueryExecutor` to execute the `CompiledQuery`.\n    - The `QueryExecutor` requests a connection from Kysely's `Driver`.\n    - The `Driver`'s job is to abstract away vendor-specific details. It communicates\n      with the actual third-party `DatabaseDriver` — for example, the `pg` or `mysql2`\n      npm package — to get a connection from its pool.\n    - A `DatabaseConnection` object, which wraps the native connection, is returned\n      to the `QueryExecutor`.\n\n    ```mermaid\n    sequenceDiagram\n        autonumber 13\n\n        participant QB as QueryBuilder\n        participant QE as QueryExecutor\n\n        box Dialect\n            participant D as Driver\n        end\n\n        actor DD as DatabaseDriver\n\n        activate QB\n\n        QB->>+QE: executeQuery(CompiledQuery)\n\n            QE->>+D: acquireConnection()\n\n                opt differs per driver\n                    D->>+DD:\n                    DD-->>-D: connection\n                end\n\n            D-->>-QE: new DatabaseConnection\n\n        deactivate QE\n        deactivate QB\n    ```\n\n1.  ### Database Query\n\n    The `QueryExecutor` passes the `CompiledQuery` to the `DatabaseConnection` object,\n    which executes it. The `DatabaseConnection` uses the underlying `DatabaseDriver`\n    to send the SQL and parameters to the database for execution. The `DatabaseDriver`\n    sends the raw results back. The `DatabaseConnection` standardizes these into\n    a `QueryResult` object and returns it to the `QueryExecutor`. Immediately after,\n    the connection is released back to the pool.\n\n    ```mermaid\n    sequenceDiagram\n        autonumber 18\n\n        participant QE as QueryExecutor\n\n        box Dialect\n            participant DC as DatabaseConnection\n        end\n\n        actor DD as DatabaseDriver\n\n        activate QE\n\n        QE->>+DC: executeQuery(CompiledQuery)\n\n            DC->>+DD: SQL + Params\n            DD-->>-DC: Raw Results\n\n        DC-->>-QE: QueryResult\n\n        deactivate QE\n    ```\n\n1.  ### Result Transformation\n\n    The `QueryResult` is then passed through the plugin system again. The `QueryExecutor`\n    calls the `transformResult` method on each plugin, allowing for final modifications\n    to the results before they are returned to the `App`.\n\n    ```mermaid\n    sequenceDiagram\n        autonumber 22\n\n        participant QE as QueryExecutor\n        participant P as Plugin\n\n        activate QE\n\n        loop all plugins\n            QE->>+P: transformResults(QueryResult)\n            P-->>-QE: Transformed QueryResult\n        end\n\n        deactivate QE\n    ```\n\n1.  ### Returning to the App\n\n    The final, transformed `QueryResult` is passed up from the `QueryExecutor`\n    to the `QueryBuilder`. The `QueryBuilder` then resolves the promise from the\n    initial `.execute()` call, delivering the final, typed results to your `App`.\n\n```mermaid\nsequenceDiagram\n    actor Y as App\n    participant QB as QueryBuilder\n    participant QE as QueryExecutor\n    participant P as Plugin\n\n    box Dialect\n        participant QC as QueryCompiler\n        participant D as Driver\n        participant DC as DatabaseConnection\n    end\n\n    actor DD as DatabaseDriver\n\n    activate Y\n\n    loop more to build\n        Y->>+QB: method(type-safe inputs)\n        QB->>QB: QueryAST\n        QB-->>Y: new QueryBuilder\n    end\n\n    Y->>QB: execute()\n\n        QB->>+QE: transformQuery(QueryAST)\n\n            loop all plugins\n                QE->>+P: transformQuery(QueryAST)\n                P-->>-QE: Transformed QueryAST\n            end\n\n        QE-->>-QB: Transformed QueryAST\n\n        QB->>+QE: compileQuery(QueryAST)\n\n            QE->>+QC: compileQuery(QueryAST)\n            QC-->>-QE: CompiledQuery\n\n        QE-->>-QB: CompiledQuery\n\n        QB->>+QE: executeQuery(CompiledQuery)\n\n            QE->>+D: acquireConnection()\n\n                opt differs per driver\n                    D->>+DD:\n                    DD-->>-D: connection\n                end\n\n            D-->>-QE: new DatabaseConnection\n\n            QE->>+DC: executeQuery(CompiledQuery)\n\n                DC->>+DD: SQL + Params\n                DD-->>-DC: Raw Results\n\n            DC-->>-QE: QueryResult\n\n            loop all plugins\n                QE->>+P: transformResults(QueryResult)\n                P-->>-QE: Transformed QueryResult\n            end\n\n        QE-->>-QB: Query Results\n\n    QB-->>-Y: Query Results\n\n    deactivate Y\n```\n"
  },
  {
    "path": "site/docs/generating-types.md",
    "content": "# Generating types\n\nTo work with Kysely, you're required to provide a database schema type definition to the Kysely constructor.\n\nIn many cases, defining your database schema definitions manually is good enough.\n\nHowever, when building production applications, it's best to stay aligned with the \ndatabase schema, by automatically generating the database schema type definitions.\n\nThere are several ways to do this using third-party libraries:\n\n- [kysely-codegen](https://github.com/RobinBlomberg/kysely-codegen) - This library \ngenerates Kysely database schema type definitions by connecting to and introspecting \nyour database. This library works with all built-in dialects.\n\n- [prisma-kysely](https://github.com/valtyr/prisma-kysely) - This library generates \nKysely database schema type definitions from your existing Prisma schemas.\n\n- [kanel-kysely](https://github.com/kristiandupont/kanel/tree/main/packages/kanel-kysely) - This\nlibrary generates Kysely database schema type definitions by connecting to and introspecting \nyour database. This library extends Kanel which is a mature PostgreSQL-only type generator.\n\n- [kysely-schema-generator](https://github.com/deanc/kysely-schema-generator) - This library \ngenerates Kysely database schema type definitions by connecting to and introspecting \nyour database. Current MySQL only.\n"
  },
  {
    "path": "site/docs/getting-started/Dialects.tsx",
    "content": "import Admonition from '@theme/Admonition'\nimport CodeBlock from '@theme/CodeBlock'\nimport Heading from '@theme/Heading'\nimport Link from '@docusaurus/Link'\nimport TabItem from '@theme/TabItem'\nimport Tabs from '@theme/Tabs'\nimport { IUseADifferentPackageManager } from './IUseADifferentPackageManager'\nimport {\n  getDriverNPMPackageNames,\n  getBashCommand,\n  getDenoCommand,\n  isDialectSupported,\n  POOL_NPM_PACKAGE_NAMES,\n  PRETTY_DIALECT_NAMES,\n  PRETTY_PACKAGE_MANAGER_NAMES,\n  type Dialect,\n  type PackageManager,\n  PACKAGE_MANAGERS,\n  type PropsWithPackageManager,\n  useSearchState,\n  DEFAULT_PACKAGE_MANAGER,\n} from './shared'\n\nexport type DialectsProps = PropsWithPackageManager\n\ninterface BuiltInDialect {\n  value: Dialect\n  driverDocsURL: string\n  poolDocsURL?: string\n}\n\nconst builtInDialects: BuiltInDialect[] = [\n  {\n    value: 'postgresql',\n    driverDocsURL: 'https://node-postgres.com/',\n  },\n  {\n    value: 'mysql',\n    driverDocsURL:\n      'https://github.com/sidorares/node-mysql2/tree/master/documentation',\n  },\n  {\n    value: 'mssql',\n    driverDocsURL: 'https://tediousjs.github.io/tedious/index.html',\n    poolDocsURL: 'https://github.com/vincit/tarn.js',\n  },\n  {\n    value: 'sqlite',\n    driverDocsURL:\n      'https://github.com/WiseLibs/better-sqlite3/blob/master/docs/api.md',\n  },\n]\n\nexport function Dialects(props: DialectsProps) {\n  const packageManager = useSearchState({\n    defaultValue: DEFAULT_PACKAGE_MANAGER,\n    searchParam: props.packageManagerSearchParam,\n    validator: (value) => PACKAGE_MANAGERS.includes(value as never),\n    value: props.packageManager,\n  })\n\n  return (\n    <>\n      <p>\n        For Kysely's query compilation and execution to work, it needs to\n        understand your database's SQL specification and how to communicate with\n        it. This requires a <code>Dialect</code> implementation.\n        <br />\n        <br />\n        There are 4 built-in dialects for PostgreSQL, MySQL, Microsoft SQL\n        Server (MSSQL), and SQLite. Additionally, the community has implemented\n        several dialects to choose from. Find out more at{' '}\n        <Link to=\"/docs/dialects\">\"Dialects\"</Link>.\n      </p>\n      <Heading as=\"h3\">Driver installation</Heading>\n      <p>\n        A <code>Dialect</code> implementation usually requires a database driver\n        library as a peer dependency. Let's install it using the same package\n        manager command from before:\n      </p>\n      {/* @ts-ignore For some odd reason, Tabs doesn't accept children in this file. */}\n      <Tabs queryString=\"dialect\">\n        {builtInDialects.map(({ driverDocsURL, poolDocsURL, value }) => {\n          const driverNPMPackage = getDriverNPMPackageNames()[value]\n          const poolNPMPackage = POOL_NPM_PACKAGE_NAMES[value]\n          const prettyDialectName = PRETTY_DIALECT_NAMES[value]\n          const installationCommand =\n            packageManager === 'deno'\n              ? getDenoCommand({\n                  [driverNPMPackage]: `npm:${driverNPMPackage}`,\n                  [`${driverNPMPackage}-pool`]:\n                    driverNPMPackage === 'pg' ? 'npm:pg-pool' : undefined,\n                })\n              : getBashCommand(packageManager, driverNPMPackage, [\n                  poolNPMPackage,\n                ])\n\n          return (\n            // @ts-ignore For some odd reason, TabItem doesn't accept children in this file.\n            <TabItem key={value} value={value} label={prettyDialectName}>\n              {!isDialectSupported(value, packageManager) ? (\n                <UnsupportedDriver\n                  dialect={prettyDialectName}\n                  driverNPMPackage={driverNPMPackage}\n                  packageManager={packageManager}\n                />\n              ) : (\n                <>\n                  <p>\n                    Kysely's built-in {prettyDialectName} dialect uses the \"\n                    {driverNPMPackage}\" driver library under the hood. Please\n                    refer to its{' '}\n                    <Link to={driverDocsURL}>official documentation</Link> for\n                    configuration options.\n                  </p>\n                  {poolNPMPackage ? (\n                    <p>\n                      Additionally, Kysely's {prettyDialectName} dialect uses\n                      the \"{poolNPMPackage}\" resource pool package for\n                      connection pooling. Please refer to its{' '}\n                      <Link to={poolDocsURL}>official documentation</Link> for\n                      configuration options.\n                    </p>\n                  ) : null}\n                  <p>\n                    <strong>{installationCommand.intro}</strong>\n                  </p>\n                  <CodeBlock\n                    language={installationCommand.language}\n                    title={installationCommand.title}\n                  >\n                    {installationCommand.content}\n                  </CodeBlock>\n                </>\n              )}\n            </TabItem>\n          )\n        })}\n      </Tabs>\n      <IUseADifferentPackageManager\n        packageManager={packageManager}\n        packageManagerSelectionID={props.packageManagerSelectionID}\n      />\n      <Admonition type=\"info\" title=\"Driverless\">\n        Kysely can also work in compile-only mode that doesn't require a\n        database driver. Find out more at{' '}\n        <Link to=\"/docs/recipes/splitting-query-building-and-execution\">\n          \"Splitting query building and execution\"\n        </Link>\n        .\n      </Admonition>\n    </>\n  )\n}\n\ninterface UnsupportedDriverProps {\n  dialect: string\n  driverNPMPackage: string\n  packageManager: PackageManager\n}\n\nfunction UnsupportedDriver(props: UnsupportedDriverProps) {\n  const { dialect, packageManager } = props\n\n  const packageManagerName =\n    PRETTY_PACKAGE_MANAGER_NAMES[packageManager || 'npm']\n\n  return (\n    <Admonition type=\"danger\" title=\"Driver unsupported\">\n      Kysely's built-in {dialect} dialect does not work in {packageManagerName}{' '}\n      because the driver library it uses, \"{props.driverNPMPackage}\", doesn't.\n      You have to use a community {dialect} dialect that works in{' '}\n      {packageManagerName}, or implement your own.\n    </Admonition>\n  )\n}\n"
  },
  {
    "path": "site/docs/getting-started/IUseADifferentDialect.tsx",
    "content": "import Link from '@docusaurus/Link'\nimport {\n  DEFAULT_DIALECT,\n  PRETTY_DIALECT_NAMES,\n  type PropsWithDialect,\n} from './shared'\n\nexport function IUseADifferentDialect(\n  props: Pick<PropsWithDialect, 'dialect' | 'dialectSelectionID'>,\n) {\n  const { dialect, dialectSelectionID } = props\n\n  if (!dialectSelectionID) {\n    return null\n  }\n\n  const dialectName = PRETTY_DIALECT_NAMES[dialect || DEFAULT_DIALECT]\n\n  return (\n    <p style={{ display: 'flex', justifyContent: 'end' }}>\n      <Link to={`#${dialectSelectionID}`}>\n        I use a different dialect (not {dialectName})\n      </Link>\n    </p>\n  )\n}\n"
  },
  {
    "path": "site/docs/getting-started/IUseADifferentPackageManager.tsx",
    "content": "import Link from '@docusaurus/Link'\nimport {\n  DEFAULT_PACKAGE_MANAGER,\n  PRETTY_PACKAGE_MANAGER_NAMES,\n  type PropsWithPackageManager,\n} from './shared'\n\nexport function IUseADifferentPackageManager(\n  props: Pick<\n    PropsWithPackageManager,\n    'packageManager' | 'packageManagerSelectionID'\n  >,\n) {\n  const { packageManager, packageManagerSelectionID } = props\n\n  if (!packageManagerSelectionID) {\n    return null\n  }\n\n  const packageManagerName =\n    PRETTY_PACKAGE_MANAGER_NAMES[packageManager || DEFAULT_PACKAGE_MANAGER]\n\n  return (\n    <p style={{ display: 'flex', justifyContent: 'end' }}>\n      <Link to={`#${packageManagerSelectionID}`}>\n        I use a different package manager (not {packageManagerName})\n      </Link>\n    </p>\n  )\n}\n"
  },
  {
    "path": "site/docs/getting-started/Installation.tsx",
    "content": "import type { ReactNode } from 'react'\nimport CodeBlock from '@theme/CodeBlock'\nimport Link from '@docusaurus/Link'\nimport Tabs from '@theme/Tabs'\nimport TabItem from '@theme/TabItem'\nimport {\n  getBashCommand,\n  getDenoCommand,\n  PRETTY_PACKAGE_MANAGER_NAMES,\n  type Command,\n  type PackageManager,\n} from './shared'\n\ninterface PackageManagerDetails {\n  value: PackageManager\n  description: ReactNode\n  command: Command\n}\n\nconst JavaScriptLink = () => (\n  <Link to=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript\">\n    JavaScript\n  </Link>\n)\nconst NodeJSLink = () => <Link to=\"https://nodejs.org\">Node.js</Link>\n\nconst packageManagers: PackageManagerDetails[] = [\n  {\n    value: 'npm',\n    description: (\n      <>\n        <Link to=\"https://npmjs.com\">{PRETTY_PACKAGE_MANAGER_NAMES.npm}</Link>{' '}\n        is the default package manager for <NodeJSLink />, and to where Kysely\n        is published.\n        <br />\n        Your project is using {PRETTY_PACKAGE_MANAGER_NAMES.npm} if it has a{' '}\n        <code>package-lock.json</code> file in its root folder.\n      </>\n    ),\n    command: getBashCommand('npm', 'kysely'),\n  },\n  {\n    value: 'pnpm',\n    description: (\n      <>\n        <Link to=\"https://pnpm.io\">{PRETTY_PACKAGE_MANAGER_NAMES.pnpm}</Link> is\n        a fast, disk space efficient package manager for <NodeJSLink />\n        .\n        <br />\n        Your project is using {PRETTY_PACKAGE_MANAGER_NAMES.pnpm} if it has a{' '}\n        <code>pnpm-lock.yaml</code> file in its root folder.\n      </>\n    ),\n    command: getBashCommand('pnpm', 'kysely'),\n  },\n  {\n    value: 'yarn',\n    description: (\n      <>\n        <Link to=\"https://yarnpkg.com\">\n          {PRETTY_PACKAGE_MANAGER_NAMES.yarn}\n        </Link>{' '}\n        is a fast, reliable and secure dependency manager for <NodeJSLink />\n        .\n        <br />\n        Your project is using {PRETTY_PACKAGE_MANAGER_NAMES.yarn} if it has a{' '}\n        <code>yarn.lock</code> file in its root folder.\n      </>\n    ),\n    command: getBashCommand('yarn', 'kysely'),\n  },\n  {\n    value: 'deno',\n    description: (\n      <>\n        <Link to=\"https://deno.com/runtime\">\n          {PRETTY_PACKAGE_MANAGER_NAMES.deno}\n        </Link>{' '}\n        is a secure runtime for <JavaScriptLink /> and{' '}\n        <Link to=\"https://www.typescriptlang.org\">TypeScript</Link>.\n      </>\n    ),\n    command: getDenoCommand(),\n  },\n  {\n    value: 'bun',\n    description: (\n      <>\n        <Link to=\"https://bun.sh\">{PRETTY_PACKAGE_MANAGER_NAMES.bun}</Link> is a\n        new <JavaScriptLink /> runtime built for speed, with a native bundler,\n        transpiler, test runner, and {PRETTY_PACKAGE_MANAGER_NAMES.npm}\n        -compatible package manager baked-in.\n      </>\n    ),\n    command: getBashCommand('bun', 'kysely'),\n  },\n]\n\nexport function Installation() {\n  return (\n    <>\n      <p>\n        Kysely can be installed using any of the following package managers:\n      </p>\n      {/* @ts-ignore For some odd reason, Tabs doesn't accept children in this file. */}\n      <Tabs queryString=\"package-manager\">\n        {packageManagers.map(({ command, value, ...packageManager }) => (\n          // @ts-ignore For some odd reason, TabItem doesn't accept children in this file.\n          <TabItem\n            key={value}\n            value={value}\n            label={PRETTY_PACKAGE_MANAGER_NAMES[value]}\n          >\n            <p>{packageManager.description}</p>\n            <p>\n              <strong>{command.intro}</strong>\n            </p>\n            <CodeBlock language={command.language} title={command.title}>\n              {command.content}\n            </CodeBlock>\n          </TabItem>\n        ))}\n      </Tabs>\n    </>\n  )\n}\n"
  },
  {
    "path": "site/docs/getting-started/Instantiation.tsx",
    "content": "import Admonition from '@theme/Admonition'\nimport CodeBlock from '@theme/CodeBlock'\nimport { IUseADifferentDialect } from './IUseADifferentDialect'\nimport { IUseADifferentPackageManager } from './IUseADifferentPackageManager'\nimport {\n  getDriverNPMPackageNames,\n  isDialectSupported,\n  POOL_NPM_PACKAGE_NAMES,\n  PRETTY_PACKAGE_MANAGER_NAMES,\n  type Dialect,\n  type PackageManager,\n  type PropsWithDialect,\n  DIALECT_CLASS_NAMES,\n  PRETTY_DIALECT_NAMES,\n  type PropsWithPackageManager,\n  useSearchState,\n  DIALECTS,\n  DEFAULT_PACKAGE_MANAGER,\n  DEFAULT_DIALECT,\n  PACKAGE_MANAGERS,\n} from './shared'\n\nexport type InstantiationProps = PropsWithDialect<PropsWithPackageManager>\n\nexport function Instantiation(props: InstantiationProps) {\n  const { dialectSelectionID, packageManagerSelectionID } = props\n\n  const dialect = useSearchState({\n    defaultValue: DEFAULT_DIALECT,\n    searchParam: props.dialectSearchParam,\n    validator: (value) => DIALECTS.includes(value as never),\n    value: props.dialect,\n  })\n  const packageManager = useSearchState({\n    defaultValue: DEFAULT_PACKAGE_MANAGER,\n    searchParam: props.packageManagerSearchParam,\n    validator: (value) => PACKAGE_MANAGERS.includes(value as never),\n    value: props.packageManager,\n  })\n\n  const dialectSpecificCodeSnippet = !isDialectSupported(\n    dialect,\n    packageManager,\n  )\n    ? getNotSupportedCode(dialect, packageManager)\n    : getDialectSpecificCodeSnippet(dialect, packageManager)\n\n  const dialectClassName = DIALECT_CLASS_NAMES[dialect]\n\n  return (\n    <>\n      <p>\n        <strong>Let's create a Kysely instance</strong>\n        {isDialectSupported(dialect, packageManager) ? (\n          <>\n            <strong> using the built-in </strong>\n            <code>{dialectClassName}</code>\n            <strong> dialect</strong>\n          </>\n        ) : (\n          <strong> assuming a compatible community dialect exists</strong>\n        )}\n        <strong>:</strong>\n      </p>\n      <CodeBlock language=\"ts\" title=\"src/database.ts\">\n        {`import { Database } from './types.ts' // this is the Database interface we defined earlier\n${dialectSpecificCodeSnippet}\n\n// Database interface is passed to Kysely's constructor, and from now on, Kysely \n// knows your database structure.\n// Dialect is passed to Kysely's constructor, and from now on, Kysely knows how \n// to communicate with your database.\nexport const db = new Kysely<Database>({\n  dialect,\n})`}\n      </CodeBlock>\n      {dialectSelectionID || packageManagerSelectionID ? (\n        <div style={{ display: 'flex', gap: '25px', justifyContent: 'end' }}>\n          <IUseADifferentPackageManager\n            packageManager={packageManager}\n            packageManagerSelectionID={packageManagerSelectionID}\n          />\n          <IUseADifferentDialect\n            dialect={dialect}\n            dialectSelectionID={dialectSelectionID}\n          />\n        </div>\n      ) : null}\n      <Admonition type=\"tip\" title=\"Singleton\">\n        In most cases, you should only create a single Kysely instance per\n        database. Most dialects use a connection pool internally, or no\n        connections at all, so there's no need to create a new instance for each\n        request.\n      </Admonition>\n      <Admonition type=\"warning\" title=\"keeping secrets\">\n        Use a secrets manager, environment variables (DO NOT commit `.env` files\n        to your repository), or a similar solution, to avoid hardcoding database\n        credentials in your code.\n      </Admonition>\n      <Admonition type=\"info\" title=\"kill it with fire\">\n        When needed, you can dispose of the Kysely instance, release resources\n        and close all connections by invoking the <code>db.destroy()</code>{' '}\n        function.\n      </Admonition>\n    </>\n  )\n}\n\nfunction getNotSupportedCode(\n  dialect: Dialect,\n  packageManager: PackageManager,\n): string {\n  return `/* Kysely doesn't support ${PRETTY_DIALECT_NAMES[dialect]} + ${\n    PRETTY_PACKAGE_MANAGER_NAMES[packageManager || 'npm']\n  } out of the box. Import a community dialect that does here. */\nimport { Kysely } from 'kysely'\n\nconst dialect = /* instantiate the dialect here */`\n}\n\nfunction getDialectSpecificCodeSnippet(\n  dialect: Dialect,\n  packageManager: PackageManager,\n): string {\n  const driverNPMPackageName = getDriverNPMPackageNames(packageManager)[dialect]\n  const dialectClassName = DIALECT_CLASS_NAMES[dialect]\n  const poolClassName = 'Pool'\n  const poolClassImport =\n    packageManager === 'deno' ? poolClassName : `{ ${poolClassName} }`\n\n  if (dialect === 'postgresql') {\n    return `import ${poolClassImport} from '${driverNPMPackageName}'\nimport { Kysely, ${dialectClassName} } from 'kysely'\n\nconst dialect = new ${dialectClassName}({\n  pool: new ${poolClassName}({\n    database: 'test',\n    host: 'localhost',\n    user: 'admin',\n    port: 5434,\n    max: 10,\n  })\n})`\n  }\n\n  if (dialect === 'mysql') {\n    const poolFactoryName = 'createPool'\n\n    return `import { ${poolFactoryName} } from '${driverNPMPackageName}' // do not use 'mysql2/promises'!\nimport { Kysely, ${dialectClassName} } from 'kysely'\n\nconst dialect = new ${dialectClassName}({\n  pool: ${poolFactoryName}({\n    database: 'test',\n    host: 'localhost',\n    user: 'admin',\n    password: '123',\n    port: 3308,\n    connectionLimit: 10,\n  })\n})`\n  }\n\n  if (dialect === 'mssql') {\n    const poolPackageName = POOL_NPM_PACKAGE_NAMES.mssql\n\n    return `import * as ${driverNPMPackageName} from '${driverNPMPackageName}'\nimport * as ${poolPackageName} from '${poolPackageName}'\nimport { Kysely, ${dialectClassName} } from 'kysely'\n\nconst dialect = new ${dialectClassName}({\n  ${poolPackageName}: {\n    ...${poolPackageName},\n    options: {\n      min: 0,\n      max: 10,\n    },\n  },\n  ${driverNPMPackageName}: {\n    ...${driverNPMPackageName},\n    connectionFactory: () => new ${driverNPMPackageName}.Connection({\n      authentication: {\n        options: {\n          password: 'password',\n          userName: 'username',\n        },\n        type: 'default',\n      },\n      options: {\n        database: 'some_db',\n        port: 1433,\n        trustServerCertificate: true,\n      },\n      server: 'localhost',\n    }),\n  },\n})`\n  }\n\n  if (dialect === 'sqlite') {\n    const driverImportName = 'SQLite'\n\n    return `import ${driverImportName} from '${driverNPMPackageName}'\nimport { Kysely, ${dialectClassName} } from 'kysely'\n\nconst dialect = new ${dialectClassName}({\n  database: new ${driverImportName}(':memory:'),\n})`\n  }\n\n  throw new Error(`Unsupported dialect: ${dialect}`)\n}\n"
  },
  {
    "path": "site/docs/getting-started/Querying.tsx",
    "content": "import Admonition from '@theme/Admonition'\nimport CodeBlock from '@theme/CodeBlock'\nimport Link from '@docusaurus/Link'\nimport { IUseADifferentDialect } from './IUseADifferentDialect'\nimport {\n  DEFAULT_DIALECT,\n  DIALECTS,\n  useSearchState,\n  type Dialect,\n  type PropsWithDialect,\n} from './shared'\n\nconst postgresqlCodeSnippet = `export async function createPerson(person: NewPerson) {\n  return await db.insertInto('person')\n    .values(person)\n    .returningAll()\n    .executeTakeFirstOrThrow()\n}\n\nexport async function deletePerson(id: number) {\n  return await db.deleteFrom('person').where('id', '=', id)\n    .returningAll()\n    .executeTakeFirst()\n}`\n\nconst dialectSpecificCodeSnippets: Record<Dialect, string> = {\n  postgresql: postgresqlCodeSnippet,\n  mysql: `export async function createPerson(person: NewPerson) {\n  const { insertId } = await db.insertInto('person')\n    .values(person)\n    .executeTakeFirstOrThrow()\n\n  return await findPersonById(Number(insertId!))\n}\n\nexport async function deletePerson(id: number) {\n  const person = await findPersonById(id)\n\n  if (person) {\n    await db.deleteFrom('person').where('id', '=', id).execute()\n  }\n\n  return person\n}`,\n  mssql: `// As of v0.27.0, Kysely doesn't support the \\`OUTPUT\\` clause. This will change\n// in the future. For now, the following implementations achieve the same results\n// as other dialects' examples, but with extra steps.\n\nexport async function createPerson(person: NewPerson) {\n  const compiledQuery = db.insertInto('person').values(person).compile()\n\n  const {\n    rows: [{ id }],\n  } = await db.executeQuery<Pick<Person, 'id'>>({\n    ...compiledQuery,\n    sql: \\`\\${compiledQuery.sql}; select scope_identity() as id\\`\n  })\n\n  return await findPersonById(id)\n}\n\nexport async function deletePerson(id: number) {\n  const person = await findPersonById(id)\n\n  if (person) {\n    await db.deleteFrom('person').where('id', '=', id).execute()\n  }\n\n  return person\n}`,\n  sqlite: postgresqlCodeSnippet,\n  // TODO: Update to use output clause once #687 is completed\n}\n\nexport function Querying(props: PropsWithDialect) {\n  const dialect = useSearchState({\n    defaultValue: DEFAULT_DIALECT,\n    searchParam: props.dialectSearchParam,\n    validator: (value) => DIALECTS.includes(value as never),\n    value: props.dialect,\n  })\n\n  const dialectSpecificCodeSnippet = dialectSpecificCodeSnippets[dialect]\n\n  return (\n    <>\n      <p>\n        <strong>Let's implement the person repository:</strong>\n      </p>\n      <CodeBlock language=\"ts\" title=\"src/PersonRepository.ts\">\n        {`import { db } from './database'\nimport { PersonUpdate, Person, NewPerson } from './types'\n\nexport async function findPersonById(id: number) {\n  return await db.selectFrom('person')\n    .where('id', '=', id)\n    .selectAll()\n    .executeTakeFirst()\n}\n\nexport async function findPeople(criteria: Partial<Person>) {\n  let query = db.selectFrom('person')\n\n  if (criteria.id) {\n    query = query.where('id', '=', criteria.id) // Kysely is immutable, you must re-assign!\n  }\n\n  if (criteria.first_name) {\n    query = query.where('first_name', '=', criteria.first_name)\n  }\n\n  if (criteria.last_name !== undefined) {\n    query = query.where(\n      'last_name',\n      criteria.last_name === null ? 'is' : '=',\n      criteria.last_name\n    )\n  }\n\n  if (criteria.gender) {\n    query = query.where('gender', '=', criteria.gender)\n  }\n\n  if (criteria.created_at) {\n    query = query.where('created_at', '=', criteria.created_at)\n  }\n\n  return await query.selectAll().execute()\n}\n\nexport async function updatePerson(id: number, updateWith: PersonUpdate) {\n  await db.updateTable('person').set(updateWith).where('id', '=', id).execute()\n}\n\n${dialectSpecificCodeSnippet}`}\n      </CodeBlock>\n      <IUseADifferentDialect\n        dialect={dialect}\n        dialectSelectionID={props.dialectSelectionID}\n      />\n      <Admonition type=\"info\" title=\"But wait, there's more!\">\n        This is a simplified example with basic CRUD operations. Kysely supports\n        many more SQL features including: joins, subqueries, complex boolean\n        logic, set operations, CTEs, functions (aggregate and window functions\n        included), raw SQL, transactions, DDL queries, etc.\n        <br />\n        Find out more at <Link to=\"/docs/category/examples\">Examples</Link>.\n      </Admonition>\n    </>\n  )\n}\n"
  },
  {
    "path": "site/docs/getting-started/Summary.tsx",
    "content": "import Admonition from '@theme/Admonition'\nimport CodeBlock from '@theme/CodeBlock'\nimport Link from '@docusaurus/Link'\nimport { IUseADifferentDialect } from './IUseADifferentDialect'\nimport {\n  DEFAULT_DIALECT,\n  DIALECTS,\n  useSearchState,\n  type Dialect,\n  type PropsWithDialect,\n} from './shared'\n\nconst dialectSpecificCodeSnippets: Record<Dialect, string> = {\n  postgresql: `    await db.schema.createTable('person')\n      .addColumn('id', 'serial', (cb) => cb.primaryKey())\n      .addColumn('first_name', 'varchar', (cb) => cb.notNull())\n      .addColumn('last_name', 'varchar')\n      .addColumn('gender', 'varchar(50)', (cb) => cb.notNull())\n      .addColumn('created_at', 'timestamp', (cb) =>\n        cb.notNull().defaultTo(sql\\`now()\\`)\n      )\n      .execute()`,\n  mysql: `    await db.schema.createTable('person')\n      .addColumn('id', 'integer', (cb) => cb.primaryKey().autoIncrement())\n      .addColumn('first_name', 'varchar(255)', (cb) => cb.notNull())\n      .addColumn('last_name', 'varchar(255)')\n      .addColumn('gender', 'varchar(50)', (cb) => cb.notNull())\n      .addColumn('created_at', 'timestamp', (cb) =>\n        cb.notNull().defaultTo(sql\\`now()\\`)\n      )\n      .execute()`,\n  // TODO: Update line 42's IDENTITY once identity(1,1) is added to core.\n  mssql: `    await db.schema.createTable('person')\n      .addColumn('id', 'integer', (cb) => cb.primaryKey().modifyEnd(sql\\`identity\\`))\n      .addColumn('first_name', 'varchar(255)', (cb) => cb.notNull())\n      .addColumn('last_name', 'varchar(255)')\n      .addColumn('gender', 'varchar(50)', (cb) => cb.notNull())\n      .addColumn('created_at', 'datetime', (cb) =>\n        cb.notNull().defaultTo(sql\\`GETDATE()\\`)\n      )\n      .execute()`,\n  sqlite: `    await db.schema.createTable('person')\n      .addColumn('id', 'integer', (cb) => cb.primaryKey().autoIncrement().notNull())\n      .addColumn('first_name', 'varchar(255)', (cb) => cb.notNull())\n      .addColumn('last_name', 'varchar(255)')\n      .addColumn('gender', 'varchar(50)', (cb) => cb.notNull())\n      .addColumn('created_at', 'timestamp', (cb) =>\n        cb.notNull().defaultTo(sql\\`current_timestamp\\`)\n      )\n      .execute()`,\n}\n\nconst dialectSpecificTruncateSnippets: Record<Dialect, string> = {\n  postgresql: `await sql\\`truncate table \\${sql.table('person')}\\`.execute(db)`,\n  mysql: `await sql\\`truncate table \\${sql.table('person')}\\`.execute(db)`,\n  mssql: `await sql\\`truncate table \\${sql.table('person')}\\`.execute(db)`,\n  sqlite: `await sql\\`delete from \\${sql.table('person')}\\`.execute(db)`,\n}\n\nexport function Summary(props: PropsWithDialect) {\n  const dialect = useSearchState({\n    defaultValue: DEFAULT_DIALECT,\n    searchParam: props.dialectSearchParam,\n    validator: (value) => DIALECTS.includes(value as never),\n    value: props.dialect,\n  })\n\n  const dialectSpecificCodeSnippet = dialectSpecificCodeSnippets[dialect]\n  const dialectSpecificTruncateSnippet =\n    dialectSpecificTruncateSnippets[dialect]\n\n  return (\n    <>\n      <p>\n        We've seen how to install and instantiate Kysely, its dialects and\n        underlying drivers. We've also seen how to use Kysely to query a\n        database.\n        <br />\n        <br />\n        <strong>Let's put it all to the test:</strong>\n      </p>\n      <CodeBlock language=\"ts\" title=\"src/PersonRepository.spec.ts\">\n        {`import { sql } from 'kysely'\nimport { db } from './database'\nimport * as PersonRepository from './PersonRepository'\n\ndescribe('PersonRepository', () => {\n  before(async () => {\n${dialectSpecificCodeSnippet}\n  })\n    \n  afterEach(async () => {\n    ${dialectSpecificTruncateSnippet}\n  })\n    \n  after(async () => {\n    await db.schema.dropTable('person').execute()\n  })\n    \n  it('should find a person with a given id', async () => {\n    await PersonRepository.findPersonById(123)\n  })\n    \n  it('should find all people named Arnold', async () => {\n    await PersonRepository.findPeople({ first_name: 'Arnold' })\n  })\n    \n  it('should update gender of a person with a given id', async () => {\n    await PersonRepository.updatePerson(123, { gender: 'woman' })\n  })\n    \n  it('should create a person', async () => {\n    await PersonRepository.createPerson({\n      first_name: 'Jennifer',\n      last_name: 'Aniston',\n      gender: 'woman',\n    })\n  })\n    \n  it('should delete a person with a given id', async () => {\n    await PersonRepository.deletePerson(123)\n  })\n})`}\n      </CodeBlock>\n      <IUseADifferentDialect\n        dialect={dialect}\n        dialectSelectionID={props.dialectSelectionID}\n      />\n      <Admonition type=\"info\" title=\"Migrations\">\n        As you can see, Kysely supports DDL queries. It also supports classic\n        \"up/down\" migrations. Find out more at{' '}\n        <Link to=\"/docs/migrations\">Migrations</Link>.\n      </Admonition>\n    </>\n  )\n}\n"
  },
  {
    "path": "site/docs/getting-started/_prerequisites.mdx",
    "content": "- [TypeScript](https://www.typescriptlang.org/)\n  - Minimum supported version [4.6](https://devblogs.microsoft.com/typescript/announcing-typescript-4-6/#indexed-access-inference-improvements).\n  - For even more type-safety and accurate inference, use version [5.4](https://devblogs.microsoft.com/typescript/announcing-typescript-5-4/#notable-behavioral-changes) or later.\n  - For improved compilation performance, use version [5.9](https://devblogs.microsoft.com/typescript/announcing-typescript-5-9/#cache-instantiations-on-mappers) or later.\n  - You must enable `strict` mode in your `tsconfig.json` file's `compilerOptions`:\n\n    ```ts title=\"tsconfig.json\"\n    {\n      // ...\n      \"compilerOptions\": {\n        // ...\n        \"strict\": true\n        // ...\n      }\n      // ...\n    }\n    ```\n"
  },
  {
    "path": "site/docs/getting-started/_types.mdx",
    "content": "For Kysely's type-safety and autocompletion to work, it needs to know your\ndatabase structure. This requires a TypeScript <code>Database</code>\ninterface, that contains table names as keys and table schema interfaces as\nvalues.\n\n**Let's define our first database interface:**\n\n```ts title=\"src/types.ts\"\nimport {\n  ColumnType,\n  Generated,\n  Insertable,\n  JSONColumnType,\n  Selectable,\n  Updateable,\n} from 'kysely'\n\nexport interface Database {\n  person: PersonTable\n  pet: PetTable\n}\n\n// This interface describes the `person` table to Kysely. Table\n// interfaces should only be used in the `Database` type above\n// and never as a result type of a query!. See the `Person`,\n// `NewPerson` and `PersonUpdate` types below.\nexport interface PersonTable {\n  // Columns that are generated by the database should be marked\n  // using the `Generated` type. This way they are automatically\n  // made optional in inserts and updates.\n  id: Generated<number>\n\n  first_name: string\n  gender: 'man' | 'woman' | 'other'\n\n  // If the column is nullable in the database, make its type nullable.\n  // Don't use optional properties. Optionality is always determined\n  // automatically by Kysely.\n  last_name: string | null\n\n  // You can specify a different type for each operation (select, insert and\n  // update) using the `ColumnType<SelectType, InsertType, UpdateType>`\n  // wrapper. Here we define a column `created_at` that is selected as\n  // a `Date`, can optionally be provided as a `string` in inserts and\n  // can never be updated:\n  created_at: ColumnType<Date, string | undefined, never>\n\n  // You can specify JSON columns using the `JSONColumnType` wrapper.\n  // It is a shorthand for `ColumnType<T, string, string>`, where T\n  // is the type of the JSON object/array retrieved from the database,\n  // and the insert and update types are always `string` since you're\n  // always stringifying insert/update values.\n  metadata: JSONColumnType<{\n    login_at: string\n    ip: string | null\n    agent: string | null\n    plan: 'free' | 'premium'\n  }>\n}\n\n// You should not use the table schema interfaces directly. Instead, you should\n// use the `Selectable`, `Insertable` and `Updateable` wrappers. These wrappers\n// make sure that the correct types are used in each operation.\n//\n// Most of the time you should trust the type inference and not use explicit\n// types at all. These types can be useful when typing function arguments.\nexport type Person = Selectable<PersonTable>\nexport type NewPerson = Insertable<PersonTable>\nexport type PersonUpdate = Updateable<PersonTable>\n\nexport interface PetTable {\n  id: Generated<number>\n  name: string\n  owner_id: number\n  species: 'dog' | 'cat'\n}\n\nexport type Pet = Selectable<PetTable>\nexport type NewPet = Insertable<PetTable>\nexport type PetUpdate = Updateable<PetTable>\n```\n\n:::tip[Codegen]\n\nFor production apps, it is recommended to automatically generate your <code>Database</code>\ninterface by introspecting your production database or Prisma schemas. Generated types\nmight differ in naming convention, internal order, etc. Find out more at [\"Generating types\"](https://kysely.dev/docs/generating-types).\n\n:::\n\n:::info[Runtime types]\n\nKysely only deals with types in the TypeScript level. The runtime JavaScript types are decided\nby the underlying third-party driver such as `pg` or `mysql2` and it's up to you to select the correct\nTypeScript types in the database interface. Kysely never touches the runtime output types in\nany way. Find out more at [\"Data types\"](https://kysely.dev/docs/recipes/data-types).\n\n:::\n"
  },
  {
    "path": "site/docs/getting-started/shared.tsx",
    "content": "import { useLocation } from '@docusaurus/router'\nimport { useEffect, useState, type ReactNode } from 'react'\nimport packageJson from '../../package.json'\n\nexport const DIALECTS = ['postgresql', 'mysql', 'sqlite', 'mssql'] as const\n\nexport type Dialect = (typeof DIALECTS)[number]\n\nexport const DEFAULT_DIALECT = 'postgresql' satisfies Dialect\n\nexport type PropsWithDialect<P = {}> = P & {\n  dialect?: Dialect\n  dialectSearchParam?: string\n  dialectSelectionID?: string\n}\n\nexport type PropsWithPackageManager<P = {}> = P & {\n  packageManager?: PackageManager\n  packageManagerSearchParam?: string\n  packageManagerSelectionID?: string\n}\n\nexport const PACKAGE_MANAGERS = ['npm', 'pnpm', 'yarn', 'deno', 'bun'] as const\n\nexport type PackageManager = (typeof PACKAGE_MANAGERS)[number]\n\nexport const DEFAULT_PACKAGE_MANAGER = 'npm' satisfies PackageManager\n\nconst PACKAGE_MANAGER_UNSUPPORTED_DIALECTS: Record<PackageManager, Dialect[]> =\n  {\n    bun: ['sqlite'],\n    deno: ['sqlite', 'mssql'],\n    npm: [],\n    pnpm: [],\n    yarn: [],\n  }\n\nexport function isDialectSupported(\n  dialect: Dialect,\n  packageManager: PackageManager,\n): boolean {\n  return !PACKAGE_MANAGER_UNSUPPORTED_DIALECTS[packageManager].includes(dialect)\n}\n\nexport const DIALECT_CLASS_NAMES = {\n  postgresql: 'PostgresDialect',\n  mysql: 'MysqlDialect',\n  mssql: 'MssqlDialect',\n  sqlite: 'SqliteDialect',\n} as const satisfies Record<Dialect, string>\n\nexport const getDriverNPMPackageNames = (\n  packageManager: PackageManager = 'npm',\n) =>\n  ({\n    postgresql: packageManager === 'deno' ? 'pg-pool' : 'pg',\n    mysql: 'mysql2',\n    mssql: 'tedious',\n    sqlite: 'better-sqlite3',\n  }) as const satisfies Record<Dialect, string>\n\nexport const POOL_NPM_PACKAGE_NAMES = {\n  mssql: 'tarn',\n} as const satisfies Partial<Record<Dialect, string>>\n\nexport const PRETTY_DIALECT_NAMES = {\n  postgresql: 'PostgreSQL',\n  mysql: 'MySQL',\n  mssql: 'Microsoft SQL Server (MSSQL)',\n  sqlite: 'SQLite',\n} as const satisfies Record<Dialect, string>\n\nexport const PRETTY_PACKAGE_MANAGER_NAMES = {\n  npm: 'npm',\n  pnpm: 'pnpm',\n  yarn: 'Yarn',\n  deno: 'Deno',\n  bun: 'Bun',\n} as const satisfies Record<PackageManager, string>\n\nconst PACKAGE_MANAGER_INSTALL_COMMANDS = {\n  npm: 'npm install',\n  pnpm: 'pnpm install',\n  yarn: 'yarn add',\n  bun: 'bun install',\n} as const satisfies Omit<Record<PackageManager, string>, 'deno'>\n\nexport interface Command {\n  content: ReactNode\n  intro: ReactNode\n  language: string\n  title: string\n}\n\nexport function getBashCommand(\n  packageManager: PackageManager,\n  installedPackage: string,\n  additionalPackages?: string[],\n): Command {\n  if (packageManager === 'deno') {\n    throw new Error('Deno has no bash command')\n  }\n\n  return {\n    content: `${\n      PACKAGE_MANAGER_INSTALL_COMMANDS[packageManager]\n    } ${installedPackage}${\n      additionalPackages?.length ? ` ${additionalPackages.join(' ')}` : ''\n    }`,\n    intro: 'Run the following command in your terminal:',\n    language: 'bash',\n    title: 'terminal',\n  }\n}\n\nexport function getDenoCommand(\n  additionalImports?: Record<string, string>,\n): Command {\n  return {\n    content: JSON.stringify(\n      {\n        imports: {\n          kysely: `npm:kysely@^${packageJson.version}`,\n          ...additionalImports,\n        },\n      },\n      null,\n      2,\n    ),\n    intro: (\n      <>\n        <strong>Your root </strong>\n        <code>deno.json</code>\n        <strong>\n          's \"imports\" field should include the following dependencies:\n        </strong>\n      </>\n    ),\n    language: 'json',\n    title: 'deno.json',\n  }\n}\n\nexport interface UseSearchStateProps<Value extends string> {\n  defaultValue?: Value\n  searchParam?: string\n  validator?: (searchValue: string | null) => boolean\n  value?: Value\n}\n\nexport function useSearchState<Value extends string>(\n  props: UseSearchStateProps<Value>,\n): Value {\n  const { defaultValue, searchParam, validator, value } = props\n\n  const [state, setState] = useState<Value>(value || defaultValue)\n  const { search } = useLocation()\n\n  useEffect(\n    function syncStateWithSearch() {\n      // value overrides search value.\n      // no search param? ignore URL.\n      if (value || !searchParam) {\n        return\n      }\n\n      const searchValue = new URLSearchParams(search).get(searchParam)\n\n      if (\n        searchValue == null ||\n        searchValue === state ||\n        (validator && !validator(searchValue))\n      ) {\n        return\n      }\n\n      setState(searchValue as Value)\n    },\n    [search],\n  )\n\n  useEffect(() => {\n    if (value && value !== state) {\n      setState(value)\n    }\n  }, [value, state])\n\n  return state\n}\n"
  },
  {
    "path": "site/docs/getting-started.mdx",
    "content": "---\nsidebar_position: 2\ntitle: 'Getting started'\n---\n\nimport BrowserOnly from '@docusaurus/BrowserOnly'\nimport Prerequisites from './getting-started/_prerequisites.mdx'\nimport { Installation } from './getting-started/Installation'\nimport Types from './getting-started/_types.mdx'\nimport { Dialects } from './getting-started/Dialects'\nimport { Instantiation } from './getting-started/Instantiation'\nimport { Querying } from './getting-started/Querying'\nimport { Summary } from './getting-started/Summary'\n\n# Getting started\n\n## Prerequisites\n\n<Prerequisites />\n\n## Installation\n\n<Installation />\n\n## Types\n\n<Types />\n\n## Dialects\n\n<Dialects\n  packageManagerSearchParam=\"package-manager\"\n  packageManagerSelectionID=\"installation\"\n/>\n\n## Instantiation\n\n<Instantiation\n  dialectSearchParam=\"dialect\"\n  dialectSelectionID=\"dialects\"\n  packageManagerSearchParam=\"package-manager\"\n  packageManagerSelectionID=\"installation\"\n/>\n\n## Querying\n\n<Querying dialectSearchParam=\"dialect\" dialectSelectionID=\"dialects\" />\n\n## Summary\n\n<Summary dialectSearchParam=\"dialect\" dialectSelectionID=\"dialects\" />\n"
  },
  {
    "path": "site/docs/integrations/_category_.json",
    "content": "{\n  \"label\": \"Integrations\",\n  \"position\": 10,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Kysely integrations with other libraries, ORMs, and AI assistants.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/integrations/llms.mdx",
    "content": "# LLMs\n\nKysely provides LLM-friendly documentation to help AI tools like **Cursor**, **Windsurf**, **GitHub Copilot**, **ChatGPT**, **Claude**, and **Claude Code** understand and work with it.\n\n`llms.txt` documentation is automatically generated and kept up-to-date with each push on GitHub and is based on the [llms.txt standard](https://llmstxt.org/).\n\n## Documentation Structure\n\nThe [llms.txt](https://kysely.dev/llms.txt) file acts as a summary and index to all the docs pages.\n\nThe [llms-full.txt](https://kysely.dev/llms-full.txt) file includes all of the Kysely docs in a single file.\n\n## Usage with AI Tools\n\n### Cursor\n\nIn Cursor, you can reference the documentation using the `@Docs` feature:\n\n1. Type `@Docs` in your prompt\n2. Reference the Kysely documentation URL: `https://kysely.dev/llms-full.txt`\n3. Ask questions about Kysely queries, types, or database operations\n\n### Windsurf\n\nFor Windsurf users:\n\n1. Reference the documentation using `@https://kysely.dev/llms-full.txt`\n2. Or add it to your `.windsurfrules` file for persistent access\n\n### ChatGPT & Claude\n\nWhen using ChatGPT or Claude:\n\n1. Mention that you're using Kysely\n2. Reference the documentation URL: `https://kysely.dev/llms-full.txt`\n3. The AI will fetch and use the documentation to provide accurate answers\n\n### GitHub Copilot\n\nWhile Copilot doesn't directly support external documentation, you can:\n\n1. Include relevant documentation snippets in your comments\n2. Reference query builder methods and types accurately for better suggestions\n\n### Claude Code\n\nFor Claude Code users:\n\n1. Reference the documentation by mentioning the URL: `https://kysely.dev/llms-full.txt`\n2. Ask Claude Code to analyze the documentation for specific Kysely patterns\n3. Use commands like: `claude -p \"Using the Kysely docs at https://kysely.dev/llms-full.txt, help me build a type-safe query\"`\n\n## Example Prompts\n\nHere are some example prompts you can use with AI tools:\n\n- \"Using Kysely, how do I build a type-safe SELECT query with JOINs?\"\n- \"Show me how to define a database schema interface for Kysely\"\n- \"How can I use transactions with Kysely?\"\n- \"Create a complex query with subqueries and aggregations\"\n- \"How to handle database migrations with Kysely?\"\n"
  },
  {
    "path": "site/docs/integrations/supabase.mdx",
    "content": "# Supabase\n\nSupabase is an open-source Firebase alternative that provides a suite of tools\nfor building applications. At the core, it is a managed PostgreSQL database vendor.\nThey provide a CLI library called `supabase` that's at the heart of their ecosystem.\nIt manages your database, migrates it and can generate TypeScript types from it.\nThey also provide a JavaScript client library called `@supabase/supabase-js` that wraps\na PostgREST API, and is pretty limited - doesn't even allow raw SQL. This is where\nKysely comes in.\n\nWe provide a bridge library called `kysely-supabase` that allows you to translate\n`supabase`'s generated TypeScript types into types compatible with Kysely.\n\n## Prerequisites\n\n1. `supabase` CLI installed and a Supabase project set up.\n\n1. `kysely` installed.\n\n1. A PostgreSQL driver installed - e.g. `pg` or `postgres`. The latter requires\n   `kysely-postgres-js` to be installed as well.\n\n## Installation\n\n```bash\nnpm i -D kysely-supabase\n```\n\n## Usage\n\n### Generate TypeScript types using `supabase` CLI\n\n```bash\nnpx supabase gen types typescript --local > path/to/supabase/generated/types/file\n```\n\n### Translate Supabase types to Kysely types\n\n```ts title=\"src/types.ts\"\nimport type { Database as SupabaseDatabase } from 'path/to/supabase/generated/types/file'\nimport type { KyselifyDatabase } from 'kysely-supabase'\n\nexport type Database = KyselifyDatabase<SupabaseDatabase>\n```\n\n### Pass translated types to Kysely constructor\n\n```ts title=\"src/db.ts\"\nimport { Kysely, PostgresDialect } from 'kysely'\nimport { Pool } from 'pg'\nimport type { Database } from './types'\n\nexport const db = new Kysely<Database>({\n  //                         ^^^^^^^^\n  dialect: new PostgresDialect({\n    pool: new Pool({\n      connectionString: process.env.DATABASE_URL,\n    }),\n  }),\n})\n```\n"
  },
  {
    "path": "site/docs/intro.mdx",
    "content": "---\nsidebar_position: 1\n---\n\nimport { DemoVideo } from '@site/src/components/DemoVideo'\n\n# Introduction\n\nKysely (pronounced “Key-Seh-Lee”) is a type-safe and autocompletion-friendly TypeScript SQL query builder. Inspired by Knex. Mainly developed for [node.js](https://nodejs.org/en/) but also\nruns on all other JavaScript environments like [deno](https://deno.land/) and [bun](https://bun.sh/).\n\n<DemoVideo />\n\nKysely makes sure you only refer to tables and columns that are visible to the part of the query you're writing. The result type only has the selected columns with correct types and aliases. As an added bonus you get autocompletion for all that stuff.\n\nAs shown in the gif above, through the pure magic of modern TypeScript, Kysely is even able to parse the alias given to `pet.name` and add the `pet_name` column to the result row type. Kysely is able to infer column names, aliases and types from selected subqueries, joined subqueries, `with` statements and pretty much anything you can think of.\n\nOf course there are cases where things cannot be typed at compile time, and Kysely offers escape hatches for these situations. See the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html) and the [DynamicModule](https://kysely-org.github.io/kysely-apidoc/classes/DynamicModule.html#ref) for more info.\n\nAll API documentation is written in the typing files and you can simply hover over the module, class or method you're using to see it in your IDE. The same documentation is also hosted [here](https://kysely-org.github.io/kysely-apidoc/).\n\nIf you start using Kysely and can't find something you'd want to use, please open an issue or join our [Discord server](https://discord.gg/xyBJ3GwvAm).\n\n## Looking for help?\n\nIf you start using Kysely and can't find something you'd want to use, please [open an issue](https://github.com/kysely-org/kysely/issues) or [join our Discord server](https://discord.gg/xyBJ3GwvAm).\n"
  },
  {
    "path": "site/docs/migrations.mdx",
    "content": "---\nsidebar_position: 4\n---\n\n# Migrations\n\n## Migration files\n\nMigration files should look like this:\n\n```ts\nimport { Kysely } from 'kysely'\n\nexport async function up(db: Kysely<any>): Promise<void> {\n  // Migration code\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n  // Migration code\n}\n```\n\nThe `up` function is called when you update your database schema to the next version and `down` when you go back to previous version. The only argument for the functions is an instance of `Kysely<any>`. It's important to use `Kysely<any>` and not `Kysely<YourDatabase>`.\n\nMigrations should never depend on the current code of your app because they need to work even when the app changes. Migrations need to be \"frozen in time\".\n\nMigrations can use the `Kysely.schema` module to modify the schema. Migrations can also run normal queries to read/modify data.\n\n## Execution order\n\nMigrations will be run in the alpha-numeric order of your migration names. An excellent way to name your migrations is to prefix them with an ISO 8601 date string.\n\nBy default, Kysely will also ensure this order matches the execution order of any previously executed migrations in your database. If the orders do not match (for example, a new migration was added alphabetically before a previously executed one), an error will be returned. This adds safety by always executing your migrations in the correct, alphanumeric order.\n\nThere is also an `allowUnorderedMigrations` option. This option will allow new migrations to be run even if they are added alphabetically before ones that have already executed. Allowing unordered migrations works well in large teams where multiple team members may add migrations at the same time in parallel commits without knowing about the other migrations. Pending (unexecuted) migrations will be run in alpha-numeric order when migrating up. When migrating down, migrations will be undone in the opposite order in which they were executed (reverse sorted by execution timestamp).\n\nTo allow unordered migrations, pass the `allowUnorderedMigrations` option to Migrator:\n\n```ts\nconst migrator = new Migrator({\n  db,\n  provider: new FileMigrationProvider(...),\n  allowUnorderedMigrations: true\n})\n```\n\n## Single file vs multiple file migrations\n\nYou don't need to store your migrations as separate files if you don't want to. You can easily implement your own MigrationProvider and give it to the Migrator class when you instantiate one.\n\n## PostgreSQL migration example\n\n```ts\nimport { Kysely, sql } from 'kysely'\n\nexport async function up(db: Kysely<any>): Promise<void> {\n  await db.schema\n    .createTable('person')\n    .addColumn('id', 'serial', (col) => col.primaryKey())\n    .addColumn('first_name', 'varchar', (col) => col.notNull())\n    .addColumn('last_name', 'varchar')\n    .addColumn('gender', 'varchar(50)', (col) => col.notNull())\n    .addColumn('created_at', 'timestamp', (col) =>\n      col.defaultTo(sql`now()`).notNull(),\n    )\n    .execute()\n\n  await db.schema\n    .createTable('pet')\n    .addColumn('id', 'serial', (col) => col.primaryKey())\n    .addColumn('name', 'varchar', (col) => col.notNull().unique())\n    .addColumn('owner_id', 'integer', (col) =>\n      col.references('person.id').onDelete('cascade').notNull(),\n    )\n    .addColumn('species', 'varchar', (col) => col.notNull())\n    .execute()\n\n  await db.schema\n    .createIndex('pet_owner_id_index')\n    .on('pet')\n    .column('owner_id')\n    .execute()\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n  await db.schema.dropTable('pet').execute()\n  await db.schema.dropTable('person').execute()\n}\n```\n\n## SQLite migration example\n\n```ts\nimport { Kysely, sql } from 'kysely'\n\nexport async function up(db: Kysely<any>): Promise<void> {\n  await db.schema\n    .createTable('person')\n    .addColumn('id', 'integer', (col) => col.primaryKey())\n    .addColumn('first_name', 'text', (col) => col.notNull())\n    .addColumn('last_name', 'text')\n    .addColumn('gender', 'text', (col) => col.notNull())\n    .addColumn('created_at', 'text', (col) =>\n      col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull(),\n    )\n    .execute()\n\n  await db.schema\n    .createTable('pet')\n    .addColumn('id', 'integer', (col) => col.primaryKey())\n    .addColumn('name', 'text', (col) => col.notNull().unique())\n    .addColumn('owner_id', 'integer', (col) =>\n      col.references('person.id').onDelete('cascade').notNull(),\n    )\n    .addColumn('species', 'text', (col) => col.notNull())\n    .execute()\n\n  await db.schema\n    .createIndex('pet_owner_id_index')\n    .on('pet')\n    .column('owner_id')\n    .execute()\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n  await db.schema.dropTable('pet').execute()\n  await db.schema.dropTable('person').execute()\n}\n```\n\n## CLI (optional)\n\nKysely offers a CLI you can use for migrations (and more). It can help you create and run migrations.\nIt is not part of the core, and your mileage may vary.\n\nFor more information, visit https://github.com/kysely-org/kysely-ctl.\n\n## Running migrations\n\nYou can then use:\n\n```ts\nconst migrator = new Migrator(migratorConfig)\nawait migrator.migrateToLatest()\n```\n\nto run all migrations that have not yet been run. See the Migrator class's documentation for more info.\n\nYou will probably want to add a simple migration script to your projects like this:\n\n```ts\nimport * as path from 'path'\nimport { Pool } from 'pg'\nimport { promises as fs } from 'fs'\nimport {\n  Kysely,\n  Migrator,\n  PostgresDialect,\n  FileMigrationProvider,\n} from 'kysely'\nimport { Database } from './types'\n\nasync function migrateToLatest() {\n  const db = new Kysely<Database>({\n    dialect: new PostgresDialect({\n      pool: new Pool({\n        host: 'localhost',\n        database: 'kysely_test',\n      }),\n    }),\n  })\n\n  const migrator = new Migrator({\n    db,\n    provider: new FileMigrationProvider({\n      fs,\n      path,\n      // This needs to be an absolute path.\n      migrationFolder: path.join(__dirname, 'some/path/to/migrations'),\n    }),\n  })\n\n  const { error, results } = await migrator.migrateToLatest()\n\n  results?.forEach((it) => {\n    if (it.status === 'Success') {\n      console.log(`migration \"${it.migrationName}\" was executed successfully`)\n    } else if (it.status === 'Error') {\n      console.error(`failed to execute migration \"${it.migrationName}\"`)\n    }\n  })\n\n  if (error) {\n    console.error('failed to migrate')\n    console.error(error)\n    process.exit(1)\n  }\n\n  await db.destroy()\n}\n\nmigrateToLatest()\n```\n\nThe migration methods use a lock on the database level and parallel calls are executed serially. This means that you can safely call migrateToLatest and other migration methods from multiple server instances simultaneously and the migrations are guaranteed to only be executed once. The locks are also automatically released if the migration process crashes or the connection to the database fails.\n\n## Reference documentation\n\n[Migrator](https://kysely-org.github.io/kysely-apidoc/classes/Migrator.html)\n"
  },
  {
    "path": "site/docs/playground.mdx",
    "content": "---\nsidebar_position: 3\n---\n\n# Playground\n\n[@wirekang](https://github.com/wirekang) has created a [playground for Kysely](https://kyse.link). You can use it to quickly test stuff out and for creating code examples for your issues, PRs and Discord messages.\n\nimport { Playground } from '../src/components/Playground'\n\n<Playground\n  code={`const person = await db\n  .selectFrom('person')\n  .select(['id', 'first_name'])\n  .where('id', '=', 1)\n  .executeTakeFirst()\n`}\n/>\n\n## Codesandbox\n\nWe also have a minimal [code sandbox example](https://codesandbox.io/s/kysely-demo-9l099t?file=/src/index.tsx:0-36).\n"
  },
  {
    "path": "site/docs/plugins.md",
    "content": "# Plugin system\n\nPlugins are classes that implement [KyselyPlugin](https://kysely-org.github.io/kysely-apidoc/interfaces/KyselyPlugin.html). Plugins are then added to the `Kysely` instance as follows:\n\n```ts\nconst db = new Kysely<Database>({\n  dialect: new PostgresDialect({\n    database: 'kysely_test',\n    host: 'localhost',\n  }),\n  plugins: [new CamelCasePlugin()],\n})\n```\n\n## Built-in plugins\n\n### Camel case plugin\n\nA plugin that converts snake_case identifiers in the database into camelCase in the JavaScript side. [Learn more](https://kysely-org.github.io/kysely-apidoc/classes/CamelCasePlugin.html).\n\n### Deduplicate joins plugin\n\nA plugin that removes duplicate joins from queries. You can read more about it in the [examples](/docs/recipes/deduplicate-joins) section or check the [API docs](https://kysely-org.github.io/kysely-apidoc/classes/DeduplicateJoinsPlugin.html).\n\n### Handle `in ()` and `not in ()` plugin\n\nA plugin that allows handling `in ()` and `not in ()` with a chosen strategy. [Learn more](https://kysely-org.github.io/kysely-apidoc/classes/HandleEmptyInListsPlugin.html).\n"
  },
  {
    "path": "site/docs/recipes/0001-relations.md",
    "content": "# Relations\n\n<h3>\nKysely IS NOT an ORM. Kysely DOES NOT have the concept of relations.\nKysely IS a query builder. Kysely DOES build the SQL you tell it to, nothing more, nothing less.\n</h3>\n\nPhew, glad we got that out the way..\n\nHaving said all that, there are ways to nest related rows in your queries. You just have to do it\nusing the tools SQL and the underlying dialect (e.g. PostgreSQL, MySQL, or SQLite) provide. In this recipe\nwe show one way to do that when using the built-in PostgreSQL, MySQL, and SQLite dialects.\n\nThis recipe is supported on MySQL versions starting from 8.0.14. This is due to the way subqueries use outer references in this recipe (cf. [MySQL 8.0.14 changelog](https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-14.html#mysqld-8-0-14-optimizer) | [MariaDB is not supported yet](https://jira.mariadb.org/browse/MDEV-19078)).\n\n## The `json` data type and functions\n\nPostgreSQL and MySQL have rich JSON support through their `json` data types and functions. `pg` and `mysql2`, the node drivers, automatically parse returned `json` columns as json objects. With the combination of these two things, we can write some super efficient queries with nested relations.\n\n:::info[Parsing JSON]\nThe built in `SqliteDialect` and some third-party dialects don't parse the returned JSON columns to objects automatically.\nNot even if they use `PostgreSQL` or `MySQL` under the hood! Parsing is handled (or not handled) by the database driver\nthat Kysely has no control over. If your JSON columns get returned as strings, you can use the `ParseJSONResultsPlugin`:\n\n```ts\nconst db = new Kysely<DB>({\n  ...\n  plugins: [new ParseJSONResultsPlugin()]\n})\n```\n:::\n\nLet's start with some raw postgres SQL, and then see how we can write the query using Kysely in a nice type-safe way.\n\nIn the following query, we fetch a list of people (from \"person\" table) and for each person, we nest the person's pets, and mother, into the returned objects:\n\n```sql\nSELECT\n  person.*,\n\n  -- Select person's pets as a json array\n  (\n    SELECT\n      COALESCE(JSON_AGG(pets), '[]')\n    FROM\n    (\n      SELECT\n        pet.id, pet.name\n      FROM\n        pet\n      WHERE\n        pet.owner_id = person.id\n      ORDER BY\n        pet.name\n    ) pets\n  ) pets,\n\n  -- Select person's mother as a json object\n  (\n    SELECT\n      TO_JSON(mother)\n    FROM\n    (\n      SELECT\n        mother.id, mother.first_name\n      FROM\n        person as mother\n      WHERE\n        mother.id = person.mother_id\n    ) mother\n  ) mother\nFROM\n  person\n```\n\nSimple right 😅. Yeah, not so much. But it does provide full control over the queries and a really good performance as long as you have indices (or indexes, we don't judge) for \"pet.owner_id\" and \"person.mother_id\".\n\nFortunately we can improve and simplify this a lot using Kysely. First let's define a couple of helpers:\n\n```ts\nfunction jsonArrayFrom<O>(expr: Expression<O>) {\n  return sql<Simplify<O>[]>`(select coalesce(json_agg(agg), '[]') from ${expr} as agg)`\n}\n\nfunction jsonObjectFrom<O>(expr: Expression<O>) {\n  return sql<Simplify<O>>`(select to_json(obj) from ${expr} as obj)`\n}\n```\n\nThese helpers are included in Kysely and you can import them from the `helpers` module like this:\n\n```ts\nimport { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres'\n```\n\nMySQL and SQLite versions of the helpers are slightly different, but you can use them the same way. You can import them like this:\n\n```ts\nimport { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/mysql'\n```\n\n```ts\nimport { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/sqlite'\n```\n\nWith these helpers, our example query already becomes a little more bearable to look at:\n\n```ts\nconst persons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .select((eb) => [\n    // pets\n    jsonArrayFrom(\n      eb.selectFrom('pet')\n        .select(['pet.id', 'pet.name'])\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .orderBy('pet.name')\n    ).as('pets'),\n\n    // mother\n    jsonObjectFrom(\n      eb.selectFrom('person as mother')\n        .select(['mother.id', 'mother.first_name'])\n        .whereRef('mother.id', '=', 'person.mother_id')\n    ).as('mother')\n  ])\n  .execute()\n\nconsole.log(persons[0].pets[0].name)\nconsole.log(persons[0].mother?.first_name)\n```\n\nThat's better right? If you need to do this over and over in your codebase, you can create some helpers like these:\n\n```ts\nfunction pets(ownerId: Expression<string>) {\n  return jsonArrayFrom(\n    db.selectFrom('pet')\n      .select(['pet.id', 'pet.name'])\n      .where('pet.owner_id', '=', ownerId)\n      .orderBy('pet.name')\n  )\n}\n\nfunction mother(motherId: Expression<string>) {\n  return jsonObjectFrom(\n    db.selectFrom('person as mother')\n      .select(['mother.id', 'mother.first_name'])\n      .where('mother.id', '=', motherId)\n  )\n}\n```\n\nAnd now you get this:\n\n```ts\nconst persons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .select(({ ref }) => [\n    pets(ref('person.id')).as('pets'),\n    mother(ref('person.mother_id')).as('mother')\n  ])\n  .execute()\n\nconsole.log(persons[0].pets[0].name)\nconsole.log(persons[0].mother?.first_name)\n```\n\nIn some cases Kysely marks your selections as nullable if it's not able to know the related object\nalways exists. If you have that information, you can mark the relation non-null using the\n`$notNull()` helper like this:\n\n```ts\nconst persons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .select(({ ref }) => [\n    pets(ref('person.id')).as('pets'),\n    mother(ref('person.mother_id')).$notNull().as('mother')\n  ])\n  .execute()\n\nconsole.log(persons[0].pets[0].name)\nconsole.log(persons[0].mother.first_name)\n```\n\nIf you need to select relations conditionally, `$if` is your friend:\n\n```ts\nconst persons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .$if(includePets, (qb) => qb.select(\n    (eb) => pets(eb.ref('person.id')).as('pets')\n  ))\n  .$if(includeMom, (qb) => qb.select(\n    (eb) => mother(eb.ref('person.mother_id')).as('mother')\n  ))\n  .execute()\n```\n"
  },
  {
    "path": "site/docs/recipes/0001-reusable-helpers.md",
    "content": "# Reusable helpers\n\n:::info\n[Here's](https://kyse.link/qm67s) a playground link containing all the code in this recipe.\n:::\n\nLet's say you want to write the following query:\n\n```sql\nSELECT id, first_name\nFROM person\nWHERE upper(last_name) = $1\n```\n\nKysely doesn't have a built-in `upper` function but there are at least three ways you could write this:\n\n```ts\nconst lastName = 'STALLONE'\n\nconst persons = await db\n  .selectFrom('person')\n  .select(['id', 'first_name'])\n  // 1. `sql` template tag. This is the least type-safe option.\n  // You're providing the column name without any type-checking,\n  // and plugins won't affect it.\n  .where(\n    sql<string>`upper(last_name)`, '=', lastName\n  )\n  // 2. `sql` template tag with `ref`. Anything passed to `ref`\n  // gets type-checked against the accumulated query context.\n  .where(({ eb, ref }) => eb(\n    sql<string>`upper(${ref('last_name')})`, '=', lastName\n  ))\n  // 3. The `fn` function helps you avoid missing parentheses/commas\n  // errors and uses refs as 1st class arguments.\n  .where(({ eb, fn }) => eb(\n    fn<string>('upper', ['last_name']), '=', lastName\n  ))\n  .execute()\n```\n\nbut each option could be more readable or type-safe.\n\nFortunately Kysely allows you to easily create composable, reusable and type-safe helper functions:\n\n```ts\nimport { Expression, sql } from 'kysely'\n\nfunction upper(expr: Expression<string>) {\n  return sql<string>`upper(${expr})`\n}\n\nfunction lower(expr: Expression<string>) {\n  return sql<string>`lower(${expr})`\n}\n\nfunction concat(...exprs: Expression<string>[]) {\n  return sql.join<string>(exprs, sql`||`)\n}\n```\n\nUsing the `upper` helper, our query would look like this:\n\n```ts\nconst lastName = 'STALLONE'\n\nconst persons = await db\n  .selectFrom('person')\n  .select(['id', 'first_name'])\n  .where(({ eb, ref }) => eb(\n    upper(ref('last_name')), '=', lastName\n  ))\n  .execute()\n```\n\nThe recipe for helper functions is simple: take inputs as `Expression<T>` instances where `T` is the type of the expression. For example `upper` takes in any `string` expression since it transforms strings to upper case. If you implemented the `round` function, it'd take in `Expression<number>` since you can only round numbers.\n\nThe helper functions should then use the inputs to create an output that's also an `Expression`. Everything you can create using the expression builder is an instance of `Expression`. So is the output of the `sql` template tag and all methods under the `sql` object. Same goes for `SelectQueryBuilder` and pretty much everything else in Kysely. Everything's an expression.\n\nSee [this recipe](https://kysely.dev/docs/recipes/expressions) to learn more about expressions.\n\nSo we've learned that everything's an expression and that expressions are composable. Let's put this idea to use:\n\n```ts\nconst persons = await db\n  .selectFrom('person')\n  .select(['id', 'first_name'])\n  .where(({ eb, ref, val }) => eb(\n    concat(\n      lower(ref('first_name')),\n      val(' '),\n      upper(ref('last_name'))\n    ),\n    '=',\n    'sylvester STALLONE'\n  ))\n  .execute()\n```\n\nSo far we've only used our helper functions in the first argument of `where` but you can use them anywhere:\n\n```ts\nconst persons = await db\n  .selectFrom('person')\n  .innerJoin('pet', (join) => join.on(eb => eb(\n    'person.first_name', '=', lower(eb.ref('pet.name'))\n  )))\n  .select(({ ref, val }) => [\n    'first_name',\n    // If you use a helper in `select`, you need to always provide an explicit\n    // name for it using the `as` method.\n    concat(ref('person.first_name'), val(' '), ref('pet.name')).as('name_with_pet')\n  ])\n  .orderBy(({ ref }) => lower(ref('first_name')))\n  .execute()\n```\n\n## Reusable helpers using `ExpressionBuilder`\n\nHere's an example of a helper function that uses the expression builder instead of raw SQL:\n\n```ts\nimport { Expression, expressionBuilder } from 'kysely'\n\nfunction idsOfPersonsThatHaveDogNamed(name: Expression<string>) {\n  const eb = expressionBuilder<DB>()\n\n  // A subquery that returns the identifiers of all persons\n  // that have a dog named `name`.\n  return eb\n    .selectFrom('pet')\n    .select('pet.owner_id')\n    .where('pet.species', '=', 'dog')\n    .where('pet.name', '=', name)\n}\n```\n\nAnd here's how you could use it:\n\n```ts\nconst dogName = 'Doggo'\n\nconst persons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .where((eb) => eb(\n    'person.id', 'in', idsOfPersonsThatHaveDogNamed(eb.val(dogName))\n  ))\n  .execute()\n```\n\nNote that `idsOfPersonsThatHaveDogNamed` doesn't execute a separate query but instead returns a subquery expression that's compiled as a part of the parent query:\n\n```sql\nselect\n  person.*\nfrom\n  person\nwhere\n  person.id in (\n    select pet.owner_id\n    from pet\n    where pet.species = 'dog'\n    and pet.name = ?\n  )\n```\n\nIn all our examples we've used the following syntax:\n\n```ts\n.where(eb => eb(left, operator, right))\n```\n\nWhen the expression builder `eb` is used as a function, it creates a binary expression. All binary expressions with a comparison operator are represented as a `Expression<SqlBool>`. You don't always need to return `eb(left, operator, right)` from the callback though. Since `Expressions` are composable and reusable, you can return any `Expression<SqlBool>`.\n\nThis means you can create helpers like this:\n\n```ts\nfunction isOlderThan(age: Expression<number>) {\n  return sql<SqlBool>`age > ${age}`\n}\n```\n\n```ts\nconst persons = await db\n  .selectFrom('person')\n  .select(['id', 'first_name'])\n  .where(({ val }) => isOlderThan(val(60)))\n  .execute()\n```\n\n## Dealing with nullable expressions\n\nIf you want your helpers to work with nullable expressions (nullable columns etc.), you can do something like this:\n\n```ts\nimport { Expression } from 'kysely'\n\n// This function accepts both nullable and non-nullable string expressions.\nfunction toInt<T extends string | null>(expr: Expression<T>) {\n  // This returns `Expression<number | null>` if `expr` is nullable\n  // and `Expression<number>` otherwise.\n  return sql<T extends null ? (number | null) : number>`(${expr})::integer`\n}\n```\n\n## Passing select queries as expressions\n\nLet's say we have the following query:\n\n```ts\nconst expr: Expression<{ name: string }> = db\n  .selectFrom('pet')\n  .select('pet.name')\n```\n\nThe expression type of our query is `Expression<{ name: string }>` but SQL allows you to use a query like that as an `Expression<string>`. In other words, SQL allows you to use single-column record types like scalars. Most of the time Kysely is able to automatically handle this case but with helper functions you need to use `$asScalar()` to convert the type. Here's an example:\n\n```ts\nconst persons = await db\n  .selectFrom('person')\n  .select((eb) => [\n    'id',\n    'first_name',\n    upper(\n      eb.selectFrom('pet')\n        .select('name')\n        .whereRef('person.id', '=', 'pet.owner_id')\n        .limit(1)\n        .$asScalar() // <-- This is needed\n        .$notNull()\n    ).as('pet_name')\n  ])\n```\n\nThe subquery is an `Expression<{ name: string }>` but our `upper` function only accepts `Expression<string>`. That's why we need to call `$asScalar()`. `$asScalar()` has no effect on the generated SQL. It's simply a type-level helper.\n\nWe also used `$notNull()` in the example because our simple `upper` function doesn't support nullable expressions."
  },
  {
    "path": "site/docs/recipes/0002-data-types.md",
    "content": "# Data types\n\nWhen talking about data types in Kysely we need to make a distinction between the two kinds of types:\n\n1. Typescript types\n2. Runtime JavaScript types\n\n## Typescript types\n\nIn Kysely, you only define TypeScript types for your tables and columns. Since TypeScript is entirely a compile-time concept, TypeScript types __can't__ affect runtime JavaScript types. If you define your column to be a `string` in TypeScript but the database returns a `number`, the runtime type doesn't magically change to `string`. You'll see a `string` in the TypeScript code, but observe a number when you run the program.\n\n:::info\nIt's up to **you** to select correct TypeScript types for your columns based on what the driver returns.\n:::\n\n## Runtime JavaScript types\n\nThe database driver, such as `pg` or `mysql2`, decides the runtime JavaScript types the queries return. Kysely never touches the runtime types the driver returns. In fact, Kysely doesn't touch the data returned by the driver in any way. It simply executes the query and returns whatever the driver returns. An exception to this rule is when you use a plugin like `CamelCasePlugin`, in which case Kysely does change the column names.\n\nYou need to read the underlying driver's documentation or otherwise figure out what the driver returns and then align the TypeScript types to match them.\n\n### Configuring runtime JavaScript types\n\nMost drivers provide a way to change the returned types. For example `pg` returns `bigint` and `numeric` types as strings by default, but often you want to configure it to return numbers instead.\n\n#### Postgres\n\nWhen using the `pg` driver, you can use the [pg-types](https://github.com/brianc/node-pg-types) package to configure the types. For example here's how you'd configure the `bigint` to be returned as a number:\n\n```ts\nimport { Kysely, PostgresDialect } from 'kysely'\nimport * as pg from 'pg'\n\nconst int8TypeId = 20\n// Map int8 to number.\npg.types.setTypeParser(int8TypeId, (val) => {\n  return parseInt(val, 10)\n})\n\nexport const db = new Kysely<Database>({\n  dialect: new PostgresDialect({\n    pool: new pg.Pool(config),\n  }),\n})\n```\n\nSee the documentation [here](https://github.com/brianc/node-pg-types) on how to figure out the correct type id.\n\n#### MySQL\n\nWhen using the `mysql2` driver, you an use the [typeCast](https://github.com/mysqljs/mysql?tab=readme-ov-file#custom-type-casting) pool property.\n\nFor example here's how you'd map `tinyint(1)` to a boolean:\n\n```ts\nimport { Kysely, MysqlDialect } from 'kysely'\nimport { createPool } from 'mysql2'\n\nexport const db = new Kysely<Database>({\n  dialect: new MysqlDialect({\n    pool: createPool({\n      ...config,\n      // Map tinyint(1) to boolean\n      typeCast(field, next) {\n        if (field.type === 'TINY' && field.length === 1) {\n          return field.string() === '1'\n        } else {\n          return next()\n        }\n      },\n    }),\n  }),\n})\n```\n\n## Type generators\n\nThere are third-party type generators such as [kysely-codegen](https://github.com/RobinBlomberg/kysely-codegen) and [kanel-kysely](https://kristiandupont.github.io/kanel/kanel-kysely.html) that automatically generate TypeScript types based on the database schema. Find out more at [\"Generating types\"](https://kysely.dev/docs/generating-types).\n\nIf these tools generate a type that doesn't match the runtime type you observe, please refer to their documentation or open an issue in their github. Kysely has no control over these libraries."
  },
  {
    "path": "site/docs/recipes/0003-raw-sql.md",
    "content": "# Raw SQL\n\nYou can execute raw SQL strings and pass raw SQL snippets to pretty much any method or function\nusing the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html).\n"
  },
  {
    "path": "site/docs/recipes/0004-splitting-query-building-and-execution.md",
    "content": "# Splitting query building and execution\n\nKysely is primarily a type-safe sql query builder.\n\nIt also does query execution, migrations, etc. in order to align with Knex's \"batteries\nincluded\" approach.\n\n## \"Cold\" Kysely instances\n\nIn order to use Kysely purely as a query builder without database driver dependencies,\nyou can instantiate it with the built-in `DummyDriver` class:\n\n```ts\nimport {\n  Generated,\n  DummyDriver,\n  Kysely,\n  PostgresAdapter,\n  PostgresIntrospector,\n  PostgresQueryCompiler,\n} from 'kysely'\n\ninterface Person {\n  id: Generated<number>\n  first_name: string\n  last_name: string | null\n}\n\ninterface Database {\n  person: Person\n}\n\nconst db = new Kysely<Database>({\n  dialect: {\n    createAdapter: () => new PostgresAdapter(),\n    createDriver: () => new DummyDriver(),\n    createIntrospector: (db) => new PostgresIntrospector(db),\n    createQueryCompiler: () => new PostgresQueryCompiler(),\n  },\n})\n```\n\nThis Kysely instance will compile to PostgreSQL sql dialect. You can brew \"dummy\"\ndialects to compile to all kinds of sql dialects (e.g. MySQL). Trying to execute\nqueries using \"cold\" kysely instances will return empty results without communicating\nwith a database.\n\n> \"Cold\" Kysely instances are not required for the following sections. You can\nuse \"hot\" kysely instances, with real drivers, if you want to.\n\n## Compile a query\n\nTo compile a query, simply call `.compile()` at the end of the query building chain:\n\n```ts\nconst compiledQuery = db\n  .selectFrom('person')\n  .select('first_name')\n  .where('id', '=', id)\n  .compile()\n\nconsole.log(compiledQuery) // { sql: 'select \"first_name\" from \"person\" where \"id\" = $1', parameters: [1], query: { ... } }\n```\n\nThe result of `.compile()` is a `CompiledQuery` object. It contains the query string\n(in `sql` field), parameters and the original Kysely-specific syntax tree used\nfor compilation.\n\nThis output alone can be used with any database driver that understands the sql\ndialect used (PostgreSQL in this example).\n\nRaw queries can be compiled as well:\n\n```ts\nimport { Selectable, sql } from 'kysely'\n\nconst compiledQuery = sql<Selectable<Person>>`select * from person where id = ${id}`.compile(db)\n\nconsole.log(compiledQuery) // { sql: 'select * from person where id = $1', parameters: [1], query: { ... } }\n```\n\n## Infer result type\n\nKysely supports inferring a (compiled) query's result type even when detached from\nquery building chains. This allows splitting query building, compilation and execution\ncode without losing type-safety.\n\n```ts\nimport { InferResult } from 'kysely'\n\nconst query = db\n  .selectFrom('person')\n  .select('first_name')\n  .where('id', '=', id)\n\ntype QueryReturnType = InferResult<typeof query> // { first_name: string }[]\n\nconst compiledQuery = query.compile()\n\ntype CompiledQueryReturnType = InferResult<typeof compiledQuery> // { first_name: string }[]\n```\n\n## Execute compiled queries\n\nThe `CompiledQuery` object returned by `.compile()` can be executed\nvia \"hot\" Kysely instances (real drivers in use):\n\n```ts\nconst compiledQuery = db\n  .selectFrom('person')\n  .select('first_name')\n  .where('id', '=', id)\n  .compile()\n\nconst results = await db.executeQuery(compiledQuery)\n```\n\nThe `QueryResult` object returned by `.executeQuery()` contains the query results'\nrows, insertId and number of affected rows (if applicable)."
  },
  {
    "path": "site/docs/recipes/0005-conditional-selects.md",
    "content": "# Conditional selects\n\nSometimes you may want to select some fields based on a runtime condition.\nSomething like this:\n\n```ts\nasync function getPerson(id: number, withLastName: boolean) {}\n```\n\nIf `withLastName` is true the person object is returned with a `last_name`\nproperty, otherwise without it.\n\nYour first thought can be to simply do this:\n\n```ts\nasync function getPerson(id: number, withLastName: boolean) {\n  let query = db.selectFrom('person').select('first_name').where('id', '=', id)\n\n  if (withLastName) {\n    // ❌ The type of `query` doesn't change here\n    query = query.select(['last_name', sql.val('person_with_last_name' as const).as('kind')])\n  }\n\n  // ❌ Wrong return type { first_name: string, kind: 'person' }\n  return await query.select(sql.val('person' as const).as('kind')).executeTakeFirstOrThrow()\n}\n```\n\nWhile that _would_ compile, the result type would be `{ first_name: string, kind: 'person' }`\nwithout the `last_name` column and `kind` being \"person_with_last_name\", which is wrong. \nWhat happens is that the type of `query` when created is something, let's say `A`. \nThe type of the query with `last_name` selection is `B` which extends `A` but also contains \ninformation about the new selection. When you assign an object of type `B` to `query` inside\nthe `if` statement, the type gets downcast to `A`.\n\n:::info\nYou _can_ write code like this to add conditional `where`, `groupBy`, `orderBy` etc.\nstatements that don't change the type of the query builder, but it doesn't work\nwith `select`, `returning`, `innerJoin` etc. that _do_ change the type of the\nquery builder.\n:::\n\nIn this simple case you could implement the method like this:\n\n```ts\nasync function getPerson(id: number, withLastName: boolean) {\n  const query = db\n    .selectFrom(\"person\")\n    .select(\"first_name\")\n    .where(\"id\", \"=\", id);\n\n  if (withLastName) {\n    // ✅ The return type is { first_name: string, last_name: string, kind: 'person_with_last_name' }\n    return await query\n      .select([\n        \"last_name\",\n        sql.val(\"person_with_last_name\").as(\"kind\"),\n      ])\n      .executeTakeFirstOrThrow();\n  }\n\n  // ✅ The return type is { first_name: string, kind: 'person' }\n  return await query\n    .select(sql.val(\"person\").as(\"kind\"))\n    .executeTakeFirstOrThrow();\n}\n```\n\nThis works fine when you have one single condition. As soon as you have two or more\nconditions the amount of code explodes if you want to keep things type-safe. You need\nto create a separate branch for every possible combination of selections or otherwise\nthe types won't be correct.\n\nThis is where the [$if](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#_if)\nmethod can help you:\n\n```ts\nasync function getPerson(id: number, withLastName: boolean) {\n  // ✅ The return type is { first_name: string, last_name?: string }\n  return await db\n    .selectFrom(\"person\")\n    .select(\"first_name\")\n    .$if(withLastName, (qb) => qb.select(\"last_name\"))\n    .where(\"id\", \"=\", id)\n    .executeTakeFirstOrThrow();\n}\n```\n\nAny selections added inside the `$if` callback will be added as optional fields to the\noutput type since we can't know if the selections were actually made before running\nthe code.\n\nA downside of `$if` is that, unlike the imperative example, it cannot result in discriminated \nunion return types - `kind` would be a union of `'person' | 'person_with_last_name'`.\n"
  },
  {
    "path": "site/docs/recipes/0006-expressions.md",
    "content": "# Expressions\n\nAn [`Expression<T>`](https://kysely-org.github.io/kysely-apidoc/interfaces/Expression.html) is the basic type-safe query building block in Kysely. Pretty much all methods accept expressions as inputs. Most internal classes like [SelectQueryBuilder](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html) and [RawBuilder](https://kysely-org.github.io/kysely-apidoc/interfaces/RawBuilder.html) (the return value of the [sql tag](https://kysely-org.github.io/kysely-apidoc/functions/sql-1.html)) are expressions themselves.\n\n`Expression<T>` represents an arbitrary SQL expression, like a binary expression (e.g. `a + b`), or a function call (e.g. `concat(arg1, ' ', arg2, ...)`). It can be any combination of those, no matter how complex. `T` is the output type of the expression.\n\n## Expression builder\n\nExpressions are usually built using an instance of [`ExpressionBuilder<DB, TB>`](https://kysely-org.github.io/kysely-apidoc/interfaces/ExpressionBuilder.html). `DB` is the same database type you give to `Kysely` when you create an instance. `TB` is the union of all table names that are visible in the context. For example `ExpressionBuilder<DB, 'person' | 'pet'>` means you can reference `person` and `pet` columns in the created expressions.\n\nYou can get an instance of the expression builder using a callback:\n\n```ts\nconst person = await db\n  .selectFrom('person')\n  // `eb` is an instance of ExpressionBuilder<DB, 'person'>\n  .select((eb) => [\n    // Call the `upper` function on `first_name`. There's a bunch of\n    // shortcuts to functions under the `fn` object such as\n    // `eb.fn.coalesce()` that provide a cleaner syntax.\n    eb.fn('upper', ['first_name']).as('upper_first_name'),\n\n    // Select a subquery\n    eb.selectFrom('pet')\n      .select('name')\n      .whereRef('pet.owner_id', '=', 'person.id')\n      .limit(1)\n      .as('pet_name'),\n\n    // Select a boolean expression\n    eb('first_name', '=', 'Jennifer').as('is_jennifer'),\n\n    // Select a static string value\n    eb.val('Some value').as('string_value'),\n\n    // Select a literal value\n    eb.lit(42).as('literal_value'),\n  ])\n  // You can also destructure the expression builder like this\n  .where(({ and, or, eb, not, exists, selectFrom }) => or([\n    and([\n      eb('first_name', '=', firstName),\n      eb('last_name', '=', lastName)\n    ]),\n    not(exists(\n      selectFrom('pet')\n        .select('pet.id')\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .where('pet.species', 'in', ['dog', 'cat'])\n    ))\n  ]))\n  .executeTakeFirstOrThrow()\n\nconsole.log(person.upper_first_name)\nconsole.log(person.pet_name)\nconsole.log(person.is_jennifer)\n```\n\nThe generated SQL:\n\n```sql\nselect\n  upper(\"first_name\") as \"upper_first_name\",\n\n  (\n    select \"name\"\n    from \"pet\"\n    where \"pet\".\"owner_id\" = \"person\".\"id\"\n    limit 1\n  ) as \"pet_name\",\n\n  \"first_name\" = $1 as \"is_jennifer\",\n  $2 as \"string_value\",\n  42 as \"literal_value\"\nfrom\n  \"person\"\nwhere (\n  (\n    \"first_name\" = $3\n    and \"last_name\" = $4\n  )\n  or not exists (\n    select \"pet.id\"\n    from \"pet\"\n    where \"pet\".\"owner_id\" = \"person\".\"id\"\n    and \"pet\".\"species\" in ($5, $6)\n  )\n)\n```\n\nIn the above query we used the expression builder in `select` and `where` methods. You can use it the same way in other methods like `having`, `on`, `orderBy`, `groupBy` etc.\n\nAll expressions are composable. You can pass expressions as arguments of any expression. All query builder methods in Kysely accept expressions and expression builder callbacks. All expression builder methods offer auto-completions and type-safety just like methods on the query builders.\n\nYou might be wondering, \"why do I need to use a callback to get the expression builder?\". \"Why not just create an instance using a global function?\". The reason is that when you use a callback, Kysely is able to infer the context correctly. The expression builder's methods only auto-complete and accept column and table names that are available in the context. In other words, using a callback provides more type-safety!\n\nThere's also a global function `expressionBuilder` you can use to create expression builders:\n\n```ts\nimport { expressionBuilder } from 'kysely'\n\n// `eb1` has type `ExpressionBuilder<DB, never>` which means there are no tables in the\n// context. This variant should be used most of the time in helper functions since you\n// shouldn't make assumptions about the calling context.\nconst eb1 = expressionBuilder<DB>()\n\n// `eb2` has type `ExpressionBuilder<DB, 'person'>`. You can reference `person` columns\n// directly in all expression builder methods.\nconst eb2 = expressionBuilder<DB, 'person'>()\n\n// In this one you'd have access to tables `person` and `pet` and all their columns.\nconst eb3 = expressionBuilder<DB, 'person' | 'pet'>()\n\nlet qb = query\n  .selectFrom('person')\n  .innerJoin('movie as m', 'm.director_id', 'person.id')\n\n// You can also provide a query builder instance and the context is inferred automatically.\n// Type of `eb` is `ExpressionBuilder<DB & { m: Movie }, 'person' | 'm'>`\nconst eb = expressionBuilder(qb)\n\nqb = qb.where(eb.not(eb.exists(\n  eb.selectFrom('pet')\n    .select('pet.id')\n    .whereRef('pet.name', '=', 'm.name')\n)))\n```\n\n## Creating reusable helpers\n\nThe expression builder can be used to create reusable helper functions.\nLet's say we have a complex `where` expression we want to reuse in multiple queries:\n\n```ts\nfunction hasDogNamed(name: string): Expression<boolean> {\n  const eb = expressionBuilder<DB, 'person'>()\n\n  return eb.exists(\n    eb.selectFrom('pet')\n      .select('pet.id')\n      .whereRef('pet.owner_id', '=', 'person.id')\n      .where('pet.species', '=', 'dog')\n      .where('pet.name', '=', name)\n  )\n}\n```\n\nThis helper can now be used in any query, and would work just fine if \"person\" table is in context:\n\n```ts\nconst doggoPersons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .where(hasDogNamed('Doggo'))\n  .execute()\n```\n\nHowever, the above helper is not very type-safe. The following code would compile, but fail at runtime:\n\n```ts\nconst bigFatFailure = await db\n  .selectFrom('movie') // <-- \"person\" table is not in context!\n  .selectAll('movie')\n  .where(hasDogNamed('Doggo')) // <-- but we're referring to \"person.id\" in our helper\n  .execute()\n```\n\nIt's better to not make assumptions about the calling context and pass in all dependencies\nas arguments. In the following example we pass in the person's id as an expression. We also\nchanged the type of `name` from `string` to `Expression<string>`, which allows us to pass\nin arbitrary expressions instead of just values.\n\n```ts\nfunction hasDogNamed(name: Expression<string>, ownerId: Expression<number>) {\n  // Create an expression builder without any tables in the context.\n  // This way we make no assumptions about the calling context.\n  const eb = expressionBuilder<DB>()\n\n  return eb.exists(\n    eb.selectFrom('pet')\n      .select('pet.id')\n      .where('pet.owner_id', '=', ownerId)\n      .where('pet.species', '=', 'dog')\n      .where('pet.name', '=', name)\n  )\n}\n```\n\nHere's how you'd use our brand new helper:\n\n```ts\nconst doggoPersons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .where((eb) => hasDogNamed(eb.val('Doggo'), eb.ref('person.id')))\n  .execute()\n```\n\nLearn more about reusable helper functions [here](https://kysely.dev/docs/recipes/reusable-helpers).\n\n## Conditional expressions\n\nIn the following, we'll only cover `where` expressions. The same logic applies to `having`, `on`, `orderBy`, `groupBy` etc.\n\n> This section should not be confused with conditional selections in `select` clauses, which is a whole 'nother topic we discuss in [this recipe](https://kysely.dev/docs/recipes/conditional-selects).\n\nHaving a set of optional filters you want to combine using `and`, is the most basic and common use case of conditional `where` expressions.\nSince the `where`, `having` and other filter functions are additive, most of the time this is enough:\n\n```ts\nlet query = db\n  .selectFrom('person')\n  .selectAll('person')\n\nif (firstName) {\n  // The query builder is immutable. Remember to replace the builder\n  // with the new one.\n  query = query.where('first_name', '=', firstName)\n}\n\nif (lastName) {\n  query = query.where('last_name', '=', lastName)\n}\n\nconst persons = await query.execute()\n```\n\nThe same query can be built using the expression builder like this:\n\n```ts\nconst persons = await db\n  .selectFrom('person')\n  .selectAll('person')\n  .where((eb) => {\n    const filters: Expression<SqlBool>[] = []\n\n    if (firstName) {\n      filters.push(eb('first_name', '=', firstName))\n    }\n\n    if (lastName) {\n      filters.push(eb('last_name', '=', lastName))\n    }\n\n    return eb.and(filters)\n  })\n  .execute()\n```\n\nUsing the latter design, you can build conditional expressions of any complexity.\n"
  },
  {
    "path": "site/docs/recipes/0007-schemas.md",
    "content": "# Working with schemas\n\nFirst of all, when we talk about schemas in this document, we mean custom\nschemas like [postgres schemas](https://www.postgresql.org/docs/14/ddl-schemas.html).\n\nThere are two common ways to use schemas:\n\n1. To group a logical set of tables under the same \"namespace\". For example\n   all tables directly related to users could live under a `user` schema.\n\n2. To have a separate namespaced copy of a set of tables for each\n   tenant in a multitenant application.\n\nKysely offers tools for both of these cases.\n\n## 1\n\nWhen you have an enumarable set of schemas, you can add them to your database interface\nlike this:\n\n```ts\ninterface Database {\n  'user.user': UserTable\n  'user.user_permission': UserPermissionTable\n  'user.permission': PermissionTable\n  pet: PetTable\n}\n```\n\nthen you can refer to the tables just like you would a normal table:\n\n```ts\ndb.selectFrom('user.user')\n  .where('username', '=', '')\n  // You can also include the full table name\n  .where('user.user.created_at', '>', createdAt)\n  .innerJoin('user.user_permission as up', 'up.user_id', 'user.user.id')\n  .innerJoin('user.permission as p', 'p.id', 'up.permission_id')\n  .selectAll()\n```\n\n## 2\n\nIn the multitenant case you have a schema per tenant and you can't add each of them to the\ndatabase interface, nor would it make sense to do so. In this case you can use the\n[withSchema](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#withSchema) method.\n\nThe `withSchema` method sets the default schema of all table references that don't explicitly\nspecify a schema:\n\n```ts\ndb.withSchema(tenant)\n  .selectFrom('user')\n  .innerJoin('user_permission as up', 'up.user_id', 'user.id')\n  .innerJoin('public.permission as p', 'p.id', 'up.permission_id')\n  .selectAll()\n```\n\nThis is the generated SQL assuming `tenant` equals `'acme'`:\n\n```sql\nselect * from \"acme\".\"user\"\ninner join \"acme\".\"user_permission\" as \"up\" on \"up\".\"user_id\" = \"acme\".\"user\".\"id\"\ninner join \"public\".\"permission\" as \"p\" on \"p\".\"id\" = \"up\".\"permission_id\"\n```\n\nIn this example we also referred to a shared table `permission` in the `public` schema.\nPlease note that you need to add a `'public.permission': PermissionTable` item in your\ndatabase schema to be able to refer to the `public.permission` table:\n\n```ts\ninterface Database {\n  // Add your tenant tables without any schema:\n  user: UserTable\n  user_permission: UserPermissionTable\n\n  // Add schemas and tables you need to explicitly reference like this:\n  'public.permission': PermissionTable\n\n  // You can also have other shared tables with or without schemas here.\n  // But keep in mind that if you want to refer to them from a `withSchema`\n  // query, you need the table name with the schema name.\n  pet: PetTable\n}\n```\n\nSee the [first case](#1) for more info.\n"
  },
  {
    "path": "site/docs/recipes/0008-deduplicate-joins.md",
    "content": "# Deduplicate joins\n\nWhen building dynamic queries, you sometimes end up in situations where the same join\ncould be added twice. Consider this query:\n\n```ts\nasync function getPerson(\n  id: number,\n  withPetName: boolean,\n  withPetSpecies: boolean\n) {\n  return await db\n    .selectFrom('person')\n    .selectAll('person')\n    .$if(withPetName, (qb) =>\n      qb\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n        .select('pet.name as pet_name')\n    )\n    .$if(withPetSpecies, (qb) =>\n      qb\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n        .select('pet.species as pet_species')\n    )\n    .where('person.id', '=', id)\n    .executeTakeFirst()\n}\n```\n\nWe have two optional selections `pet_name` and `pet_species`. Both of them require\nthe `pet` table to be joined, but we don't want to add an unnecessary join if both\n`withPetName` and `withPetSpecies` are `false`.\n\nBut if both `withPetName` and `withPetSpecies` are `true`, we end up with two identical\njoins which will cause an error in the database.\n\nTo prevent the error from happening, you can install the\n[DeduplicateJoinsPlugin](https://kysely-org.github.io/kysely-apidoc/classes/DeduplicateJoinsPlugin.html).\nYou can either install it globally by providing it in the configuration:\n\n```ts\nconst db = new Kysely<Database>({\n  dialect,\n  plugins: [new DeduplicateJoinsPlugin()],\n})\n```\n\nor you can use it when needed:\n\n```ts\nasync function getPerson(\n  id: number,\n  withPetName: boolean,\n  withPetSpecies: boolean\n) {\n  return await db\n    .withPlugin(new DeduplicateJoinsPlugin())\n    .selectFrom('person')\n    .selectAll('person')\n    .$if(withPetName, (qb) =>\n      qb\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n        .select('pet.name as pet_name')\n    )\n    .$if(withPetSpecies, (qb) =>\n      qb\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n        .select('pet.species as pet_species')\n    )\n    .where('person.id', '=', id)\n    .executeTakeFirst()\n}\n```\n\nYou may wonder why this is a plugin and not the default behavior? The reason is that it's surprisingly\ndifficult to detect if two joins are identical. It's trivial for simple joins like the ones in the\nexample, but becomes quite complex with arbitrary joins with nested subqueries etc. There may be\ncorner cases where the `DeduplicateJoinsPlugin` fails and we don't want it to affect people that\ndon't need this deduplication (most people).\n\nSee [this recipe](/docs/recipes/conditional-selects)\nif you are wondering why we are using the `$if` method.\n"
  },
  {
    "path": "site/docs/recipes/0009-excessively-deep-types.md",
    "content": "# Dealing with the `Type instantiation is excessively deep and possibly infinite` error\n\nKysely uses complex type magic to achieve its type safety. This complexity is sometimes\ntoo much for TypeScript and you get errors like this:\n\n```\nerror TS2589: Type instantiation is excessively deep and possibly infinite.\n```\n\nIn these case you can often use the [$assertType](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#_assertType)\nmethod to help TypeScript a little bit. When you use this method to assert the output type of a query, Kysely can drop the\ncomplex output type that consists of multiple nested helper types and replace it with the simple asserted type.\n\nUsing this method doesn't reduce type safety at all. You have to pass in a type that is structurally equal to the current type.\n\nFor example having more than 12 `with` statements in a query can lead to the `TS2589` error:\n\n```ts\nconst res = await db\n  .with('w1', (qb) => qb.selectFrom('person').select('first_name as fn1'))\n  .with('w2', (qb) => qb.selectFrom('person').select('first_name as fn2'))\n  .with('w3', (qb) => qb.selectFrom('person').select('first_name as fn3'))\n  .with('w4', (qb) => qb.selectFrom('person').select('first_name as fn4'))\n  .with('w5', (qb) => qb.selectFrom('person').select('first_name as fn5'))\n  .with('w6', (qb) => qb.selectFrom('person').select('first_name as fn6'))\n  .with('w7', (qb) => qb.selectFrom('person').select('first_name as fn7'))\n  .with('w8', (qb) => qb.selectFrom('person').select('first_name as fn8'))\n  .with('w9', (qb) => qb.selectFrom('person').select('first_name as fn9'))\n  .with('w10', (qb) => qb.selectFrom('person').select('first_name as fn10'))\n  .with('w11', (qb) => qb.selectFrom('person').select('first_name as fn11'))\n  .with('w12', (qb) => qb.selectFrom('person').select('first_name as fn12'))\n  .with('w13', (qb) => qb.selectFrom('person').select('first_name as fn13'))\n  .selectFrom(['w1', 'w2', 'w3', 'w4', 'w5', 'w6', 'w7', 'w8', 'w9', 'w10', 'w11', 'w12', 'w13'])\n  .selectAll()\n  .executeTakeFirstOrThrow()\n```\n\nBut if you simplify one or more of the `with` statements using `$assertType`, you get rid of the error:\n\n```ts\nconst res = await db\n  .with('w1', (qb) => qb.selectFrom('person').select('first_name as fn1'))\n  .with('w2', (qb) => qb.selectFrom('person').select('first_name as fn2'))\n  .with('w3', (qb) => qb.selectFrom('person').select('first_name as fn3'))\n  .with('w4', (qb) => qb.selectFrom('person').select('first_name as fn4'))\n  .with('w5', (qb) => qb.selectFrom('person').select('first_name as fn5'))\n  .with('w6', (qb) => qb.selectFrom('person').select('first_name as fn6'))\n  .with('w7', (qb) => qb.selectFrom('person').select('first_name as fn7'))\n  .with('w8', (qb) => qb.selectFrom('person').select('first_name as fn8'))\n  .with('w9', (qb) => qb.selectFrom('person').select('first_name as fn9'))\n  .with('w10', (qb) => qb.selectFrom('person').select('first_name as fn10'))\n  .with('w11', (qb) => qb.selectFrom('person').select('first_name as fn11'))\n  .with('w12', (qb) =>\n    qb\n      .selectFrom('person')\n      .select('first_name as fn12')\n      .$assertType<{ fn12: string }>()\n  )\n  .with('w13', (qb) =>\n    qb\n      .selectFrom('person')\n      .select('first_name as fn13')\n      .$assertType<{ fn13: string }>()\n  )\n  .selectFrom(['w1', 'w2', 'w3', 'w4', 'w5', 'w6', 'w7', 'w8', 'w9', 'w10', 'w11', 'w12', 'w13'])\n  .selectAll()\n  .executeTakeFirstOrThrow()\n```\n\nThe type you provide for `$assertType` must be structurally equal to the return type of the subquery. Therefore no type safety is lost.\n\nI know what you're thinking: \"can't this be done automatically?\" No, unfortunately it can't. There's no way to do this using current TypeScript features. Typescript drags along all the parts the type is built with. Even though it could simplify the type into a simple object, it doesn't. We need to explictly tell it to do that.\n\n\"But there's this `Simplify` helper I've seen and it does exactly what you need\". You mean this one:\n\n```ts\nexport type Simplify<T> = { [K in keyof T]: T[K] } & {}\n```\n\nWhile that does simplify the type when you hover over it in your IDE, it doesn't actually drop the complex type underneath. You can try this yourself with the example above.\n"
  },
  {
    "path": "site/docs/recipes/0010-extending-kysely.md",
    "content": "# Extending kysely\n\nIn many cases, Kysely doesn't provide a built-in type-safe method for a feature. It's often because adding\nthat feature in a generic way that would work in all use cases is difficult or impossible.\nIn many cases it's better to create little helper functions in your project that suit your use case.\nKysely makes this simple.\n\nThe Kysely API is designed around two interfaces [`Expression<T>`](https://kysely-org.github.io/kysely-apidoc/interfaces/Expression.html)\nand [`AliasedExpression<T, A>`](https://kysely-org.github.io/kysely-apidoc/interfaces/AliasedExpression.html).\nAlmost every method accepts values that implement these interfaces and most Kysely internals achieve\ntheir \"type magic\" by implementing them.\n\nMost of the time you can create your helpers using the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html)\nand the `RawBuilder<T>` and `AliasedRawBuilder<T, A>` class instances it returns, but it's good to first understand how\nthe underlying interfaces they implement, `Expression<T>` and `AliasedExpression<T, A>`, work.\n\n## Expression\n\n[`Expression<T>`](https://kysely-org.github.io/kysely-apidoc/interfaces/Expression.html) is a simple interface\nthat has a type `T` and a single method `toOperationNode()`. `T` tells Kysely's type system the type of\nthe expression. `toOperationNode()` returns instructions on what SQL should be produced once the\nexpression is compiled.\n\nHere's an example of a custom expression for `JSON` or `JSONB` values on PostgreSQL:\n\n```ts\nimport { Expression, Kysely, OperationNode, sql } from 'kysely'\n\nclass JsonValue<T> implements Expression<T> {\n  #value: T\n\n  constructor(value: T) {\n    this.#value = value\n  }\n\n  // This is a mandatory getter. You must add it and always return `undefined`.\n  // The return type must always be `T | undefined`.\n  get expressionType(): T | undefined {\n    return undefined\n  }\n\n  toOperationNode(): OperationNode {\n    const json = JSON.stringify(this.#value)\n    // Most of the time you can use the `sql` template tag to build the returned node.\n    // The `sql` template tag takes care of passing the `json` string as a parameter, alongside the sql string, to the DB.\n    return sql`CAST(${json} AS JSONB)`.toOperationNode()\n  }\n}\n```\n\nNow you can use your new `JsonValue` expression pretty much anywhere _as a value_ in a type-safe way:\n\n```ts\ninterface DB {\n  person: {\n    address: {\n      postalCode: string\n      street: string\n    }\n  }\n}\n\nasync function test(db: Kysely<DB>) {\n  await db\n    .insertInto('person')\n    .values({\n      address: new JsonValue({\n        postalCode: '123456',\n        street: 'Kysely avenue 42',\n      }),\n    })\n    .execute()\n\n  await db\n    .selectFrom('person')\n    .selectAll()\n    .where(\n      'address',\n      '@>',\n      new JsonValue({ postalCode: '123456', street: 'Kysely avenue 42' })\n    )\n    .execute()\n}\n```\n\nMost of the time you don't need to create your own classes that implement the `Expression<T>` interface.\nYou can simply wrap the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html) and\nthe `RawBuilder<T>` class instance it returns in a function. `RawBuilder<T>`, like most things in Kysely,\nimplements the `Expression<T>` interface.\n\nOur previous example would get simplified into this:\n\n```ts\nimport { Kysely, RawBuilder, sql } from 'kysely'\n\nfunction json<T>(value: T): RawBuilder<T> {\n  return sql`CAST(${JSON.stringify(value)} AS JSONB)`\n}\n```\n\nAnd you'd use it like this:\n\n```ts\ninterface DB {\n  person: {\n    address: {\n      postalCode: string\n      street: string\n    }\n  }\n}\n\nasync function test(db: Kysely<DB>) {\n  await db\n    .insertInto('person')\n    .values({\n      address: json({\n        postalCode: '123456',\n        street: 'Kysely avenue 42',\n      }),\n    })\n    .execute()\n\n  await db\n    .selectFrom('person')\n    .selectAll()\n    .where(\n      'address',\n      '@>',\n      json({ postalCode: '123456', street: 'Kysely avenue 42' })\n    )\n    .execute()\n}\n```\n\n## AliasedExpression\n\nWhile `Expression<T>` holds the type and compilation instructions of an SQL expression,\n[`AliasedExpression<T, A>`](https://kysely-org.github.io/kysely-apidoc/interfaces/AliasedExpression.html)\nalso holds an alias (a name) for that expression. `AliasedExpression<T, A>` can be used in places\nwhere you need a name for the expression, like in a `SELECT` statement or a `FROM` statement.\n`AliasedExpression<T, A>` is how kysely is able to infer the name and type of result columns.\n\nLet's expand the `JsonValue` example from the [previous section](#expression). We'll add an `as`\nmethod for the `JsonValue` class that can be used to turn an `Expression<T>` into an `AliasedExpression<T, A>`:\n\n```ts\nimport {\n  Expression,\n  AliasedExpression,\n  Kysely,\n  OperationNode,\n  sql,\n  AliasNode,\n  IdentifierNode,\n} from 'kysely'\n\nclass JsonValue<T> implements Expression<T> {\n  // ... Methods from the previous example ...\n\n  as<A extends string>(alias: A): AliasedJsonValue<T, A> {\n    return new AliasedJsonValue(this, alias)\n  }\n}\n\nclass AliasedJsonValue<T, A extends string> implements AliasedExpression<T, A> {\n  #expression: Expression<T>\n  #alias: A\n\n  constructor(expression: Expression<T>, alias: A) {\n    this.#expression = expression\n    this.#alias = alias\n  }\n\n  get expression(): Expression<T> {\n    return this.#expression\n  }\n\n  get alias(): A {\n    return this.#alias\n  }\n\n  toOperationNode(): AliasNode {\n    return AliasNode.create(\n      this.#expression.toOperationNode(),\n      IdentifierNode.create(this.#alias)\n    )\n  }\n}\n```\n\nAnd now you can use `JsonValue` in `select` statements too with full type safety:\n\n```ts\ninterface DB {\n  person: {\n    address: {\n      postalCode: string\n      street: string\n    }\n  }\n}\n\nasync function test(db: Kysely<DB>) {\n  const result = await db\n    .selectFrom('person')\n    .select([new JsonValue({ someValue: 42 }).as('some_object'), 'address'])\n    .where(\n      'address',\n      '@>',\n      new JsonValue({ postalCode: '123456', street: 'Kysely avenue 42' })\n    )\n    .executeTakeFirstOrThrow()\n\n  console.log(result.some_object.someValue)\n  console.log(result.address.postalCode)\n}\n```\n\nAgain, in most cases you don't need to implement your own `AliasedExpression<T, A>`.\n`RawBuilder` has a similar `as` method and we can use the three line long `json`\nfunction from our previous example:\n\n```ts\nfunction json<T>(value: T): RawBuilder<T> {\n  return sql`CAST(${JSON.stringify(value)} AS JSONB)`\n}\n```\n\n```ts\ninterface DB {\n  person: {\n    address: {\n      postalCode: string\n      street: string\n    }\n  }\n}\n\nasync function test(db: Kysely<DB>) {\n  const result = await db\n    .selectFrom('person')\n    .select([json({ someValue: 42 }).as('some_object'), 'address'])\n    .where(\n      'address',\n      '@>',\n      json({ postalCode: '123456', street: 'Kysely avenue 42' })\n    )\n    .executeTakeFirstOrThrow()\n\n  console.log(result.address.postalCode)\n  console.log(result.some_object.someValue)\n}\n```\n\n## A more complex example\n\nConsider this query:\n\n```sql\ninsert into\n  t (t1, t2)\nselect\n  v.v1,\n  j.j2\nfrom\n  (values ($1, $2, $3), ($4, $5, $6)) as v(id, v1, v2)\ninner join\n  j on v.id = j.vid\n```\n\nKysely doesn't have built-in support for the `values` keyword in this context, but you can create\na type-safe helper function like this:\n\n```ts\nfunction values<R extends Record<string, unknown>, A extends string>(\n  records: R[],\n  alias: A\n): AliasedRawBuilder<R, A> {\n  // Assume there's at least one record and all records\n  // have the same keys.\n  const keys = Object.keys(records[0])\n\n  // Transform the records into a list of lists such as\n  // ($1, $2, $3), ($4, $5, $6)\n  const values = sql.join(\n    records.map((r) => sql`(${sql.join(keys.map((k) => r[k]))})`)\n  )\n\n  // Create the alias `v(id, v1, v2)` that specifies the table alias\n  // AND a name for each column.\n  const wrappedAlias = sql.ref(alias)\n  const wrappedColumns = sql.join(keys.map(sql.ref))\n  const aliasSql = sql`${wrappedAlias}(${wrappedColumns})`\n\n  // Finally create a single `AliasedRawBuilder` instance of the\n  // whole thing. Note that we need to explicitly specify\n  // the alias type using `.as<A>` because we are using a\n  // raw sql snippet as the alias.\n  return sql<R>`(values ${values})`.as<A>(aliasSql)\n}\n```\n\nA lot is going on in this function, but it's all documented in the\n[sql template tag's documentation.](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html)\n\nMost of the time a helper like this would return either an instance of `RawBuilder` or\n`AliasedRawBuilder` and you'd create an instance using the `sql` template tag. You'd return a\n`RawBuilder` instance when only the data type of a column/table is needed and an `AliasedRawBuilder`\nwhen also the name of the column/table is needed. Our example function creates kind of a temporary\ntable, so we need to tell Kysely both the type of the table AND the name of the table.\n\nThis is how you could now create our query using the `values` helper:\n\n```ts\n// This could come as an input from somewhere.\nconst records = [\n  {\n    id: 1,\n    v1: 'foo',\n    v2: 'bar',\n  },\n  {\n    id: 2,\n    v1: 'baz',\n    v2: 'spam',\n  },\n]\n\ndb.insertInto('t')\n  .columns(['t1', 't2'])\n  .expression(\n    // The `values` function automatically parses the column types\n    // from the records and you can refer to them through the table\n    // alias `v`. This works because Kysely is able to parse the\n    // AliasedRawBuilder<T, A> type.\n    db\n      .selectFrom(values(records, 'v'))\n      .innerJoin('j', 'v.id', 'j.vid')\n      .select(['v.v1', 'j.j2'])\n  )\n```\n\n## Extending using inheritance\n\nYou usually don't want to do this because of the complexity of the types and TypeScript's limitations\nwhen it comes to inheritence and return types.\nYou'll quickly run into problems.\nEven though Kysely uses classes, it is not designed from the OOP point of view.\nClasses are used because they are supported natively by TypeScript. They provide private\nvariables and a nice discoverable API.\n\n## Extending using module augmentation\n\n> DISCLAIMER: We do not support this method. Use at your own risk.\n\nYou can override and extend Kysely's builder classes via [Typescript module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation).\n\nThe following example adds an `addIdColumn` method to `CreateTableBuilder`, which helps\nin adding a PostgreSQL UUID primary key column:\n\n```ts\ndeclare module 'kysely/dist/cjs/schema/create-table-builder' {\n  interface CreateTableBuilder<TB extends string, C extends string = never> {\n    addIdColumn<CN extends string = 'id'>(\n      col?: CN\n    ): CreateTableBuilder<TB, C | CN>\n  }\n}\nCreateTableBuilder.prototype.addIdColumn = function (\n  this: CreateTableBuilder<any, any>,\n  col?: string\n) {\n  return this.addColumn(col || 'id', 'uuid', (col) =>\n    col.primaryKey().defaultTo(sql`gen_random_uuid()`)\n  )\n}\n```\n\nNow you can use `addIdColumn` seamlessly to create several tables with a uniform\nprimary key definition:\n\n```ts\ndb.schema.createTable('person').addIdColumn().addColumn('name', 'varchar')\ndb.schema.createTable('pet').addColumn('species', 'varchar').addIdColumn()\n```\n"
  },
  {
    "path": "site/docs/recipes/0011-introspecting-relation-metadata.md",
    "content": "# Introspecting relation metadata\n\nExtracting metadata about tables and views from your database schema in runtime is possible using the methods in the `instrospection` property of a `Kysely` instance.\n\nThe example below uses a PostgreSQL connection to print information about all tables and views found in the database schema:\n\n```ts\nimport { Kysely, PostgresDialect } from 'kysely'\nimport pg from 'pg'\nconst { Pool } = pg\n\nasync function logDatabaseSchema() {\n  const db = new Kysely({\n    dialect: new PostgresDialect({\n      pool: new Pool({\n        connectionString: process.env.DATABASE_URL,\n      }),\n    }),\n  })\n\n  const tables = await db.introspection.getTables()\n  //        ^?  TableMetadata[]\n\n  console.log({ tables })\n}\n\nlogDatabaseSchema()\n```\n\nFor more information check the docs for details on the interfaces [DatabaseIntrospector](https://kysely-org.github.io/kysely-apidoc/interfaces/DatabaseIntrospector.html) and [TableMetadata](https://kysely-org.github.io/kysely-apidoc/interfaces/TableMetadata.html).\n"
  },
  {
    "path": "site/docs/recipes/0012-logging.md",
    "content": "# Logging\n\nIt is possible to set up logs for all queries using the `log` property when instantiating `Kysely`.\n\nThere are 2 ways to configure logging:\n\n## 1. Provide an array with log level/s\n\nYou can provide an array of log levels to the `log` property when instantiating `Kysely`.\n\nWhen `'query'` is included in the array, `Kysely` will log all executed queries, not including parameter values.\n\nWhen `'error'` is included in the array, `Kysely` will log all errors.\n\n```ts\nconst db = new Kysely({\n  ...\n  log: ['query', 'error']\n  ...\n});\n```\n\n## 2. Provide a custom logging function\n\nYou can provide a custom logging function to the `log` property when instantiating `Kysely`. The custom logging function receives a log event as an argument.\n\nThe `LogEvent` interface is defined as follows:\n\n```ts\ninterface LogEvent {\n  level: 'query' | 'error';\n  query: CompiledQuery; // this object contains the raw SQL string, parameters, and Kysely's SQL syntax tree that helped output the raw SQL string.\n  queryDurationMillis: number; // the time in milliseconds it took for the query to execute and get a response from the database.\n  error: unknown; // only present if `level` is `'error'`.\n}\n```\n\nExample:\n\n```ts\nconst db = new Kysely({\n  dialect: new PostgresDialect(postgresConfig),\n  log(event) {\n    if (event.level === \"error\") {\n        console.error(\"Query failed : \", {\n          durationMs: event.queryDurationMillis,\n          error: event.error,\n          sql: event.query.sql,\n          params: event.query.parameters.map(maskPII),\n        });\n    } else { // `'query'`\n      console.log(\"Query executed : \", {\n        durationMs: event.queryDurationMillis,\n        sql: event.query.sql,\n        params: event.query.parameters.map(maskPII),\n      });\n    }\n  }\n})\n```\n\nFor more information check the docs for details on the interfaces [KyselyConfig](https://kysely-org.github.io/kysely-apidoc/interfaces/KyselyConfig.html).\n"
  },
  {
    "path": "site/docs/recipes/_category_.json",
    "content": "{\n  \"label\": \"Recipes\",\n  \"position\": 6,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"A list of guides or recipes explaning how to use various features of the library. These are more advanced topics, make sure you familiriaze yourself with the examples first.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/runtimes/_category_.json",
    "content": "{\n  \"label\": \"Other runtimes\",\n  \"position\": 10,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Kysely works on the browser, Node.js and Deno. Here are some examples of how to use it.\"\n  }\n}\n"
  },
  {
    "path": "site/docs/runtimes/browser.md",
    "content": "# Browser\n\nKysely also runs in the browser. Here's a minimal example:\n\n```ts\nimport {\n  Kysely,\n  Generated,\n  DummyDriver,\n  SqliteAdapter,\n  SqliteIntrospector,\n  SqliteQueryCompiler,\n} from 'kysely'\n\ninterface Person {\n  id: Generated<number>\n  first_name: string\n  last_name: string | null\n}\n\ninterface Database {\n  person: Person\n}\n\nconst db = new Kysely<Database>({\n  dialect: {\n    createAdapter() {\n      return new SqliteAdapter()\n    },\n    createDriver() {\n      return new DummyDriver()\n    },\n    createIntrospector(db: Kysely<unknown>) {\n      return new SqliteIntrospector(db)\n    },\n    createQueryCompiler() {\n      return new SqliteQueryCompiler()\n    },\n  },\n})\n\nwindow.addEventListener('load', () => {\n  const sql = db.selectFrom('person').select('id').compile()\n\n  const result = document.createElement('span')\n  result.id = 'result'\n  result.innerHTML = sql.sql\n\n  document.body.appendChild(result)\n})\n```\n"
  },
  {
    "path": "site/docs/runtimes/deno.mdx",
    "content": "---\nsidebar_position: 6\ntitle: 'Running on Deno'\n---\n\n# Running on Deno\n\nKysely doesn't include drivers for Deno, but you can still use Kysely as a query builder or implement your own driver:\n\n```ts\n// We use jsdeliver to get Kysely from npm.\nimport {\n  DummyDriver,\n  Generated,\n  Kysely,\n  PostgresAdapter,\n  PostgresIntrospector,\n  PostgresQueryCompiler,\n} from 'https://cdn.jsdelivr.net/npm/kysely/dist/esm/index.js'\n\ninterface Person {\n  id: Generated<number>\n  first_name: string\n  last_name: string | null\n}\n\ninterface Database {\n  person: Person\n}\n\nconst db = new Kysely<Database>({\n  dialect: {\n    createAdapter() {\n      return new PostgresAdapter()\n    },\n    createDriver() {\n      // You need a driver to be able to execute queries. In this example\n      // we use the dummy driver that never does anything.\n      return new DummyDriver()\n    },\n    createIntrospector(db: Kysely<unknown>) {\n      return new PostgresIntrospector(db)\n    },\n    createQueryCompiler() {\n      return new PostgresQueryCompiler()\n    },\n  },\n})\n\nconst query = db.selectFrom('person').select('id')\nconst sql = query.compile()\n\nconsole.log(sql.sql)\n```\n"
  },
  {
    "path": "site/docusaurus.config.ts",
    "content": "import type {\n  Options as PresetClassicOptions,\n  ThemeConfig as PresetClassicThemeConfig,\n} from '@docusaurus/preset-classic'\nimport type { Config } from '@docusaurus/types'\nimport type { MermaidConfig } from 'mermaid'\nimport { themes } from 'prism-react-renderer'\nimport type { PluginOptions as LLMsTXTPluginOptions } from '@signalwire/docusaurus-plugin-llms-txt'\nimport type { PluginOptions as VercelAnalyticsPluginOptions } from '@docusaurus/plugin-vercel-analytics'\n\nexport default {\n  baseUrl: '/',\n  favicon: 'img/favicon.ico',\n  i18n: {\n    defaultLocale: 'en',\n    locales: ['en'],\n  },\n  markdown: {\n    mdx1Compat: {\n      admonitions: false,\n      comments: false,\n      headingIds: false,\n    },\n    mermaid: true,\n  },\n  onBrokenAnchors: 'throw',\n  onBrokenLinks: 'throw',\n  onBrokenMarkdownLinks: 'throw',\n  onDuplicateRoutes: 'throw',\n  organizationName: 'kysely-org',\n  plugins: [\n    [\n      '@signalwire/docusaurus-plugin-llms-txt',\n      {\n        content: {\n          // https://www.npmjs.com/package/@signalwire/docusaurus-plugin-llms-txt#content-selectors\n          contentSelectors: [\n            '.theme-doc-markdown', // Docusaurus main content area\n            'main .container .col', // Bootstrap-style layout\n            'main .theme-doc-wrapper', // Docusaurus wrapper\n            'article', // Semantic article element\n            'main .container', // Broader container\n            'main', // Fallback to main element\n            '.code-example',\n          ],\n          enableLlmsFullTxt: true,\n          includeGeneratedIndex: false,\n          includePages: true,\n          includeVersionedDocs: false,\n          relativePaths: false,\n        },\n        depth: 3,\n        onRouteError: 'throw',\n        siteDescription:\n          'The most powerful type-safe SQL query builder for TypeScript',\n        siteTitle: 'Kysely',\n      } satisfies LLMsTXTPluginOptions,\n    ],\n    [\n      'vercel-analytics',\n      { debug: true, mode: 'auto' } satisfies Omit<\n        VercelAnalyticsPluginOptions,\n        'id'\n      >,\n    ],\n  ],\n  presets: [\n    [\n      'classic',\n      {\n        blog: false,\n        docs: {\n          editUrl: 'https://github.com/kysely-org/kysely/tree/master/site',\n          sidebarPath: require.resolve('./sidebars.js'),\n        },\n        theme: {\n          customCss: [\n            require.resolve('./src/css/custom.css'),\n            require.resolve('@radix-ui/colors/sky.css'),\n            require.resolve('@radix-ui/colors/gray.css'),\n            require.resolve('@radix-ui/colors/blue.css'),\n            require.resolve('@radix-ui/colors/green.css'),\n            require.resolve('@radix-ui/colors/yellow.css'),\n          ],\n        },\n      } satisfies PresetClassicOptions,\n    ],\n  ],\n  projectName: 'kysely',\n  tagline: 'The most powerful type-safe SQL query builder for TypeScript',\n  themeConfig: {\n    algolia: {\n      // Public API key, safe to expose. See https://docusaurus.io/docs/search#using-algolia-docsearch\n      apiKey: 'ebee59ab1b71803be5983f6dbfeea352',\n      appId: 'MDKJWTIJFR',\n      contextualSearch: true,\n      indexName: 'kysely',\n    },\n    colorMode: {\n      defaultMode: 'dark',\n      disableSwitch: false,\n      respectPrefersColorScheme: true,\n    },\n    docs: {\n      sidebar: {\n        autoCollapseCategories: true,\n        hideable: true,\n      },\n    },\n    footer: {\n      links: [\n        {\n          items: [\n            { label: 'Introduction', to: '/docs/intro' },\n            { label: 'Getting started', to: '/docs/getting-started' },\n            { label: 'Playground', to: '/docs/playground' },\n            { label: 'Migrations', to: '/docs/migrations' },\n            // { label: 'Examples', to: '/docs/category/examples' },\n            { label: 'Recipes', to: '/docs/category/recipes' },\n            { label: 'Other runtimes', to: '/docs/category/other-runtimes' },\n            { label: 'Dialects', to: '/docs/dialects' },\n            { label: 'Generating types', to: '/docs/generating-types' },\n            { label: 'Plugin system', to: '/docs/plugins' },\n          ],\n          title: 'Docs',\n        },\n        {\n          items: [\n            { label: 'SELECT', to: '/docs/category/select' },\n            { label: 'WHERE', to: '/docs/category/where' },\n            { label: 'JOIN', to: '/docs/category/join' },\n            { label: 'INSERT', to: '/docs/category/insert' },\n            { label: 'UPDATE', to: '/docs/category/update' },\n            { label: 'DELETE', to: '/docs/category/delete' },\n            { label: 'Transactions', to: '/docs/category/transactions' },\n            { label: 'CTE', to: '/docs/category/cte' },\n          ],\n          title: 'Examples',\n        },\n        {\n          items: [\n            {\n              label: 'Discord',\n              href: 'https://discord.gg/xyBJ3GwvAm',\n            },\n            {\n              label: 'Bluesky',\n              href: 'https://bsky.app/profile/kysely.dev',\n            },\n          ],\n          title: 'Community',\n        },\n        {\n          items: [\n            {\n              label: 'GitHub',\n              href: 'https://github.com/kysely-org/kysely',\n            },\n            {\n              label: 'API docs',\n              href: 'https://kysely-org.github.io/kysely-apidoc/',\n            },\n          ],\n          title: 'Other',\n        },\n        {\n          items: [\n            {\n              html: `<a href=\"https://vercel.com/?utm_source=kysely&utm_campaign=oss\"><img src=\"/img/powered-by-vercel.svg\" style=\"width: 214px; height: 44px\" alt=\"Powered by Vercel\" /></a>`,\n            },\n          ],\n          title: 'Sponsors',\n        },\n      ],\n      style: 'dark',\n    },\n    headTags: [\n      {\n        attributes: {\n          href: 'https://fonts.googleapis.com',\n          rel: 'preconnect',\n        },\n        tagName: 'link',\n      },\n      {\n        attributes: {\n          crossOrigin: 'anonymous',\n          href: 'https://fonts.gstatic.com',\n          rel: 'preconnect',\n        },\n        tagName: 'link',\n      },\n      {\n        attributes: {\n          as: 'style',\n          onLoad: \"this.onload=null;this.rel='stylesheet'\",\n          href: 'https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap',\n          rel: 'preload',\n        },\n        tagName: 'link',\n      },\n      {\n        attributes: {\n          as: 'image',\n          fetchpriority: 'high',\n          href: '/demo-poster.webp',\n          rel: 'preload',\n        },\n        tagName: 'link',\n      },\n    ],\n    mermaid: {\n      options: {\n        sequence: {\n          mirrorActors: false,\n          showSequenceNumbers: true,\n        },\n      } satisfies MermaidConfig,\n    },\n    metadata: [\n      {\n        content:\n          'Kysely is the most powerful type-safe SQL query builder for TypeScript. Get unparalleled autocompletion and compile-time type safety for complex queries, joins, and subqueries. Used in production by Deno, Maersk, and Cal.com. Modern TypeScript, zero runtime overhead.',\n        name: 'description',\n      },\n    ],\n    navbar: {\n      items: [\n        {\n          docId: 'intro',\n          label: 'Docs',\n          position: 'left',\n          type: 'doc',\n        },\n        {\n          href: 'https://github.com/kysely-org/kysely',\n          label: 'GitHub',\n          position: 'right',\n        },\n        {\n          href: 'https://kysely-org.github.io/kysely-apidoc',\n          label: 'API docs',\n          position: 'right',\n        },\n      ],\n      logo: {\n        alt: 'Kysely Logo',\n        height: 32,\n        src: 'img/logo.svg',\n        width: 32,\n      },\n      style: 'dark',\n      title: 'Kysely',\n    },\n    prism: {\n      darkTheme: themes.dracula,\n      theme: themes.github,\n    },\n  } satisfies PresetClassicThemeConfig,\n  themes: ['@docusaurus/theme-mermaid'],\n  title: 'Kysely',\n  url: 'https://kysely.dev',\n} satisfies Config\n"
  },
  {
    "path": "site/package.json",
    "content": "{\n  \"name\": \"kysely-site\",\n  \"version\": \"0.28.14\",\n  \"private\": true,\n  \"scripts\": {\n    \"docusaurus\": \"docusaurus\",\n    \"start\": \"docusaurus start\",\n    \"build\": \"docusaurus build\",\n    \"swizzle\": \"docusaurus swizzle\",\n    \"deploy\": \"docusaurus deploy\",\n    \"clear\": \"docusaurus clear\",\n    \"serve\": \"docusaurus serve\",\n    \"write-translations\": \"docusaurus write-translations\",\n    \"write-heading-ids\": \"docusaurus write-heading-ids\",\n    \"typecheck\": \"tsc\"\n  },\n  \"dependencies\": {\n    \"@docusaurus/core\": \"^3.9.2\",\n    \"@docusaurus/plugin-vercel-analytics\": \"^3.9.2\",\n    \"@docusaurus/preset-classic\": \"^3.9.2\",\n    \"@docusaurus/theme-common\": \"^3.9.2\",\n    \"@docusaurus/theme-mermaid\": \"^3.9.2\",\n    \"@mdx-js/react\": \"^3.1.1\",\n    \"@radix-ui/colors\": \"^3.0.0\",\n    \"clsx\": \"^2.1.1\",\n    \"prism-react-renderer\": \"^2.3.1\",\n    \"react\": \"^19.2.4\",\n    \"react-dom\": \"^19.2.4\"\n  },\n  \"devDependencies\": {\n    \"@docusaurus/module-type-aliases\": \"^3.9.2\",\n    \"@docusaurus/tsconfig\": \"^3.9.2\",\n    \"@docusaurus/types\": \"^3.9.2\",\n    \"@signalwire/docusaurus-plugin-llms-txt\": \"^1.2.2\",\n    \"@types/react\": \"^19.2.14\",\n    \"mermaid\": \"^11.13.0\",\n    \"typescript\": \"^5.9.3\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.5%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  },\n  \"engines\": {\n    \"node\": \">=20.0\"\n  },\n  \"packageManager\": \"pnpm@10.16.1+sha512.0e155aa2629db8672b49e8475da6226aa4bdea85fdcdfdc15350874946d4f3c91faaf64cbdc4a5d1ab8002f473d5c3fcedcd197989cf0390f9badd3c04678706\"\n}\n"
  },
  {
    "path": "site/sidebars.js",
    "content": "/**\n * Creating a sidebar enables you to:\n - create an ordered group of docs\n - render a sidebar for each doc of that group\n - provide next/previous navigation\n\n The sidebars can be generated from the filesystem, or explicitly defined here.\n\n Create as many sidebars as you want.\n */\n\n// @ts-check\n\n/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */\nconst sidebars = {\n  // By default, Docusaurus generates a sidebar from the docs folder structure\n  tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }],\n\n  // But you can create a sidebar manually\n  /*\n  tutorialSidebar: [\n    'intro',\n    'hello',\n    {\n      type: 'category',\n      label: 'Tutorial',\n      items: ['tutorial-basics/create-a-document'],\n    },\n  ],\n   */\n}\n\nmodule.exports = sidebars\n"
  },
  {
    "path": "site/src/components/DemoVideo.module.css",
    "content": ".videoContainer {\n  background: transparent;\n  max-width: 832px;\n  position: relative;\n  width: 100%;\n}\n\n.videoContainer video {\n  background: transparent;\n  border: none;\n  border-radius: 24px;\n  display: block;\n  height: auto;\n  margin: 0;\n  max-height: 610px;\n  outline: none;\n  padding: 0;\n  width: 100%;\n}\n"
  },
  {
    "path": "site/src/components/DemoVideo.tsx",
    "content": "import { useEffect, useRef } from 'react'\nimport styles from './DemoVideo.module.css'\n\nexport function DemoVideo() {\n  const videoRef = useRef<HTMLVideoElement>(null)\n\n  useEffect(() => {\n    const { current: video } = videoRef\n\n    if (!video) {\n      return\n    }\n\n    video.load()\n\n    const handleCanPlay = () => {\n      video.play().catch(() => {})\n      video.removeEventListener('canplay', handleCanPlay)\n    }\n\n    video.addEventListener('canplay', handleCanPlay)\n\n    return () => {\n      video.removeEventListener('canplay', handleCanPlay)\n    }\n  }, [])\n\n  return (\n    <div className={styles.videoContainer}>\n      <video\n        height=\"610\"\n        loop\n        muted\n        playsInline\n        poster=\"/demo-poster.webp\"\n        preload=\"none\"\n        ref={videoRef}\n        width=\"824\"\n      >\n        <source src=\"/demo_optimized.webm\" type=\"video/webm\" />\n        <source src=\"/demo.mp4\" type=\"video/mp4\" />\n      </video>\n    </div>\n  )\n}\n"
  },
  {
    "path": "site/src/components/Playground.module.css",
    "content": ".playground {\n  border: 1px solid var(--gray-3);\n  border-radius: 7px;\n  min-height: 600px;\n  width: 100%;\n}\n\n.visuallyHidden {\n  border: 0;\n  clip: rect(0, 0, 0, 0);\n  height: 1px;\n  margin: -1px;\n  overflow: hidden;\n  padding: 0;\n  position: absolute;\n  width: 1px;\n}\n"
  },
  {
    "path": "site/src/components/Playground.tsx",
    "content": "import { useColorMode } from '@docusaurus/theme-common'\nimport { useEffect, useRef, useState } from 'react'\nimport styles from './Playground.module.css'\nimport { GENERATED_PLAYGROUND_EXAMPLE_TYPES } from './playground-example-types'\nimport clsx from 'clsx'\nimport CodeBlock from '@theme/CodeBlock'\n\nexport function Playground(props: PlaygroundProps) {\n  const src = useSrc(props)\n  const [loadFailed, setLoadFailed] = useState<boolean>(false)\n  const iframeRef = useRef<HTMLIFrameElement | null>(null)\n\n  useEffect(() => {\n    const { current: iframe } = iframeRef\n\n    if (!iframe) {\n      return\n    }\n\n    let failTimer: NodeJS.Timeout\n\n    const handleLoad = () => {\n      clearTimeout(failTimer)\n    }\n\n    iframe.addEventListener('load', handleLoad)\n\n    failTimer = setTimeout(() => {\n      setLoadFailed(true)\n    }, 2_000)\n\n    return () => {\n      iframe.removeEventListener('load', handleLoad)\n      clearTimeout(failTimer)\n    }\n  }, [src])\n\n  return (\n    <>\n      {!loadFailed && (\n        <iframe\n          allow=\"clipboard-write\"\n          autoFocus\n          className={styles.playground}\n          ref={iframeRef}\n          src={src}\n        />\n      )}\n      <div\n        className={clsx(\n          'code-example',\n          !loadFailed ? styles.visuallyHidden : undefined,\n        )}\n      >\n        <CodeBlock language=\"ts\">\n          {[GENERATED_PLAYGROUND_EXAMPLE_TYPES, props.setupCode, props.code]\n            .filter(Boolean)\n            .join('\\n\\n')}\n        </CodeBlock>\n      </div>\n    </>\n  )\n}\n\nfunction useSrc(props: PlaygroundProps) {\n  const { colorMode } = useColorMode()\n  const [src, setSrc] = useState('')\n\n  useEffect(() => {\n    const params = new URLSearchParams()\n\n    params.set('theme', colorMode)\n    params.set('notheme', '1')\n\n    if (!props.disableIframeMode) {\n      params.set('open', '1')\n      params.set('nomore', '1')\n      params.set('nohotkey', '1')\n    }\n\n    setSrc(`https://kyse.link/?${params}${getPlaygroundStateHash(props)}`)\n  }, [colorMode])\n\n  return src\n}\n\nfunction getPlaygroundStateHash(props: PlaygroundProps) {\n  const { kyselyVersion } = props\n\n  const state: PlaygroundState = {\n    dialect: props.dialect || 'postgres',\n    editors: { query: props.code, type: GENERATED_PLAYGROUND_EXAMPLE_TYPES },\n    hideType: true,\n  }\n\n  if (kyselyVersion) {\n    state.kysely = { type: 'tag', name: kyselyVersion }\n  }\n\n  return '#r' + encodeURIComponent(JSON.stringify(state))\n}\n\ninterface PlaygroundProps {\n  kyselyVersion?: string\n  dialect?: 'postgres'\n  code: string\n  setupCode?: string\n  disableIframeMode: boolean\n}\n\ninterface PlaygroundState {\n  dialect: 'postgres' | 'mysql' | 'mssql' | 'sqlite'\n  editors: {\n    type: string\n    query: string\n  }\n  hideType?: boolean\n  kysely?: {\n    type: 'tag' | 'branch'\n    name: string\n  }\n}\n"
  },
  {
    "path": "site/src/components/SectionFeatures/index.tsx",
    "content": "import type { JSX, SVGProps } from 'react'\nimport clsx from 'clsx'\nimport styles from './styles.module.css'\n\ntype FeatureItem = {\n  title: string\n  description: string | JSX.Element\n}\n\nconst FeatureList: FeatureItem[] = [\n  {\n    title: 'Type-safety without compromises',\n    description: (\n      <>\n        Kysely's state-of-the-art, type-safe API provides precise result types\n        and catches errors within queries at compile-time, giving\n        high-performing teams the confidence to ship at greater velocity. Use\n        `kysely-codegen` to make the database the source of types.\n      </>\n    ),\n  },\n  {\n    title: 'What you see is what you get',\n    description: (\n      <>\n        Kysely is a thin abstraction layer over SQL, crafted by SQL lovers for\n        SQL lovers, focusing on familiarity through naming and structure, and\n        predictability through 1:1 compilation. Teams proficient in SQL can pick\n        up Kysely and be productive in minutes.\n      </>\n    ),\n  },\n  {\n    title: 'Write with great auto-completion',\n    description: (\n      <>\n        Your database schema types flow through Kysely's fluent API, offering a\n        typing experience that's second only to full-blown database IDEs. Get\n        intelligent, context-aware suggestions for functions, table names, and\n        column names as you type.\n      </>\n    ),\n  },\n  {\n    title: 'Build SQL queries with unmatched depth',\n    description: (\n      <>\n        Kysely supports building a wide range of SQL queries, clauses,\n        functions, and expressions, including SELECT, INSERT, UPDATE, DELETE,\n        MERGE, WITH, and more. When needed, you can also use raw SQL strings,\n        even within structured queries.\n      </>\n    ),\n  },\n  {\n    title: 'Query any SQL database',\n    description: (\n      <>\n        Kysely's community-driven dialect system makes it easy to implement\n        support for any SQL database without waiting for the core team. It ships\n        with official dialects for PostgreSQL, MySQL, MS SQL Server, and SQLite\n        right out of the box.\n      </>\n    ),\n  },\n  {\n    title: 'Run anywhere',\n    description: (\n      <>\n        Kysely is lightweight, ships both CommonJS and ESM, has zero\n        dependencies, and avoids any environment-specific APIs. It can run in\n        any JavaScript environment, including Node.js, Deno, Bun, AWS Lambda,\n        Cloudflare Workers, and browsers.\n      </>\n    ),\n  },\n  {\n    title: 'Take control over your migrations',\n    description: (\n      <>\n        Kysely includes optional up/down migration primitives, allowing you to\n        move away from risky black box migration tools and write your own\n        migrations. Use `kysely-ctl` to run your migrations directly in the\n        terminal or within your CI/CD pipeline.\n      </>\n    ),\n  },\n  {\n    title: 'Extend with plugins',\n    description: (\n      <>\n        Kysely's plugin system allows you tap into the process, and modify\n        queries before compilation and/or their results after execution. This\n        opens up various use cases, such as transforming camelCase names to\n        snake_case and vice versa.\n      </>\n    ),\n  },\n]\n\nfunction TickIcon(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"122.877\"\n      height=\"101.052\"\n      x=\"0\"\n      y=\"0\"\n      version=\"1.1\"\n      viewBox=\"0 0 122.877 101.052\"\n      xmlSpace=\"preserve\"\n      {...props}\n    >\n      <path d=\"M4.43 63.63A14.383 14.383 0 01.003 53.52a14.393 14.393 0 014.015-10.281 14.372 14.372 0 0110.106-4.425 14.373 14.373 0 0110.283 4.012l24.787 23.851L98.543 3.989l1.768 1.349-1.77-1.355a2.27 2.27 0 01.479-.466A14.383 14.383 0 01109.243.022V.018l.176.016c3.623.24 7.162 1.85 9.775 4.766a14.383 14.383 0 013.662 10.412h.004l-.016.176a14.362 14.362 0 01-4.609 9.632L59.011 97.11l.004.004a2.157 2.157 0 01-.372.368 14.392 14.392 0 01-9.757 3.569 14.381 14.381 0 01-9.741-4.016L4.43 63.63z\"></path>\n    </svg>\n  )\n}\n\nfunction Feature({ title, description }: FeatureItem) {\n  return (\n    <div className={clsx('col col--6')} style={{ padding: 10 }}>\n      <div className=\"padding-horiz--md\">\n        <h3 className={styles.featureTitle}>\n          <span className={styles.tickContainer}>\n            <TickIcon className={styles.tickIcon} />\n          </span>\n          {title}\n        </h3>\n        <p className={styles.featureDescription}>{description}</p>\n      </div>\n    </div>\n  )\n}\n\nexport function SectionFeatures(): JSX.Element {\n  return (\n    <section className={styles.features}>\n      <div className=\"container\">\n        <h2 className={styles.sectionHeading}>Show this to your boss!</h2>\n        <div className=\"row\">\n          {FeatureList.map((props, idx) => (\n            <Feature key={idx} {...props} />\n          ))}\n        </div>\n      </div>\n    </section>\n  )\n}\n"
  },
  {
    "path": "site/src/components/SectionFeatures/styles.module.css",
    "content": ".features {\n  display: flex;\n  align-items: center;\n  width: 100%;\n  position: relative;\n  min-height: 80vh;\n  padding: 64px 0;\n}\n\n[data-theme='dark'] .features {\n  background-color: var(--gray-12);\n}\n\n.featureTitle {\n  align-items: center;\n  color: var(--gray-12);\n  display: inline-flex;\n  gap: 8px;\n}\n\n[data-theme='dark'] .featureTitle {\n  color: var(--gray-4);\n}\n\n.tickContainer {\n  background-color: var(--sky-7);\n  border: 1px solid var(--sky-10);\n  border-radius: 100%;\n  display: grid;\n  font-size: 12px;\n  height: 20px;\n  place-items: center;\n  width: 20px;\n}\n\n.tickIcon {\n  height: 12px;\n  fill: var(--sky-12);\n  width: 12px;\n}\n\n.featureDescription {\n  color: var(--gray-11);\n}\n\n[data-theme='dark'] .featureDescription {\n  color: var(--gray-8);\n}\n\n.sectionHeading {\n  margin-bottom: 2rem;\n  text-align: center;\n}\n"
  },
  {
    "path": "site/src/components/SectionQuotes/Quote.tsx",
    "content": "import clsx from 'clsx'\nimport type { ReactElement } from 'react'\n\nimport styles from './styles.module.css'\nimport redditStyles from './reddit.module.css'\n\nexport interface QuoteProps {\n  avatar: string\n  authorName: string\n  authorTitle: string\n  link: string\n  text: string\n}\n\nconst domainNameToIcon: Record<string, ReactElement> = {\n  discord: <DiscordIcon />,\n  github: <GithubIcon />,\n  reddit: <RedditIcon />,\n  x: <XIcon />,\n}\n\nexport function Quote(props: QuoteProps) {\n  const { authorName, authorTitle, avatar, link, text } = props\n\n  const [domainName] = new URL(link).hostname.split('.')\n\n  // Construct paths from avatar filename\n  const webpSrc = `/img/avatars/${avatar}.webp`\n  const jpgSrc = `/img/avatars/${avatar}.jpg`\n\n  return (\n    <a className={styles.quoteContainer} href={link} target=\"_blank\">\n      <div className={styles.quoteInnerContainer}>\n        <picture>\n          <source srcSet={webpSrc} type=\"image/webp\" />\n          <img\n            alt={`${authorName}'s avatar picture`}\n            className=\"avatar__photo\"\n            src={jpgSrc}\n          />\n        </picture>\n        <div className={styles.quoteHeader}>\n          <span className={styles.quoteTitle}>{authorName}</span>\n          <small className={styles.quoteSubtitle}>{authorTitle}</small>\n        </div>\n      </div>\n\n      <small className={styles.quoteText}>{text}</small>\n      {domainNameToIcon[domainName] || null}\n    </a>\n  )\n}\n\nfunction XIcon() {\n  return (\n    <svg\n      className={clsx(styles.icon, styles.darkIcon)}\n      height=\"271\"\n      viewBox=\"0 0 271 300\"\n      width=\"300\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path d=\"m236 0h46l-101 115 118 156h-92.6l-72.5-94.8-83 94.8h-46l107-123-113-148h94.9l65.5 86.6zm-16.1 244h25.5l-165-218h-27.4z\" />\n    </svg>\n  )\n}\n\nfunction DiscordIcon() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className={styles.icon}\n      preserveAspectRatio=\"xMidYMid\"\n      version=\"1.1\"\n      viewBox=\"0 -28.5 256 256\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <g>\n        <path\n          d=\"M216.856339,16.5966031 C200.285002,8.84328665 182.566144,3.2084988 164.041564,0 C161.766523,4.11318106 159.108624,9.64549908 157.276099,14.0464379 C137.583995,11.0849896 118.072967,11.0849896 98.7430163,14.0464379 C96.9108417,9.64549908 94.1925838,4.11318106 91.8971895,0 C73.3526068,3.2084988 55.6133949,8.86399117 39.0420583,16.6376612 C5.61752293,67.146514 -3.4433191,116.400813 1.08711069,164.955721 C23.2560196,181.510915 44.7403634,191.567697 65.8621325,198.148576 C71.0772151,190.971126 75.7283628,183.341335 79.7352139,175.300261 C72.104019,172.400575 64.7949724,168.822202 57.8887866,164.667963 C59.7209612,163.310589 61.5131304,161.891452 63.2445898,160.431257 C105.36741,180.133187 151.134928,180.133187 192.754523,160.431257 C194.506336,161.891452 196.298154,163.310589 198.110326,164.667963 C191.183787,168.842556 183.854737,172.420929 176.223542,175.320965 C180.230393,183.341335 184.861538,190.991831 190.096624,198.16893 C211.238746,191.588051 232.743023,181.531619 254.911949,164.955721 C260.227747,108.668201 245.831087,59.8662432 216.856339,16.5966031 Z M85.4738752,135.09489 C72.8290281,135.09489 62.4592217,123.290155 62.4592217,108.914901 C62.4592217,94.5396472 72.607595,82.7145587 85.4738752,82.7145587 C98.3405064,82.7145587 108.709962,94.5189427 108.488529,108.914901 C108.508531,123.290155 98.3405064,135.09489 85.4738752,135.09489 Z M170.525237,135.09489 C157.88039,135.09489 147.510584,123.290155 147.510584,108.914901 C147.510584,94.5396472 157.658606,82.7145587 170.525237,82.7145587 C183.391518,82.7145587 193.761324,94.5189427 193.539891,108.914901 C193.539891,123.290155 183.391518,135.09489 170.525237,135.09489 Z\"\n          fill=\"#5865F2\"\n          fillRule=\"nonzero\"\n        />\n      </g>\n    </svg>\n  )\n}\n\nfunction GithubIcon() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className={clsx(styles.icon, styles.darkIcon)}\n      width=\"98\"\n      height=\"96\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 98 96\"\n    >\n      <path\n        clipRule=\"evenodd\"\n        d=\"M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z\"\n        fillRule=\"evenodd\"\n      />\n    </svg>\n  )\n}\n\nfunction RedditIcon() {\n  return (\n    <svg\n      className={clsx(styles.icon, styles.darkIcon)}\n      width=\"16\"\n      height=\"16\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 216 216\"\n      xmlSpace=\"preserve\"\n      xmlnsXlink=\"http://www.w3.org/1999/xlink\"\n    >\n      <defs>\n        <radialGradient\n          id=\"snoo-radial-gragient\"\n          cx=\"169.75\"\n          cy=\"92.19\"\n          fx=\"169.75\"\n          fy=\"92.19\"\n          r=\"50.98\"\n          gradientTransform=\"translate(0 11.64) scale(1 .87)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop offset=\"0\" stopColor=\"#feffff\" />\n          <stop offset=\".4\" stopColor=\"#feffff\" />\n          <stop offset=\".51\" stopColor=\"#f9fcfc\" />\n          <stop offset=\".62\" stopColor=\"#edf3f5\" />\n          <stop offset=\".7\" stopColor=\"#dee9ec\" />\n          <stop offset=\".72\" stopColor=\"#d8e4e8\" />\n          <stop offset=\".76\" stopColor=\"#ccd8df\" />\n          <stop offset=\".8\" stopColor=\"#c8d5dd\" />\n          <stop offset=\".83\" stopColor=\"#ccd6de\" />\n          <stop offset=\".85\" stopColor=\"#d8dbe2\" />\n          <stop offset=\".88\" stopColor=\"#ede3e9\" />\n          <stop offset=\".9\" stopColor=\"#ffebef\" />\n        </radialGradient>\n        <radialGradient\n          id=\"snoo-radial-gragient-2\"\n          cx=\"47.31\"\n          fx=\"47.31\"\n          r=\"50.98\"\n          xlinkHref=\"#snoo-radial-gragient\"\n        />\n        <radialGradient\n          id=\"snoo-radial-gragient-3\"\n          cx=\"109.61\"\n          cy=\"85.59\"\n          fx=\"109.61\"\n          fy=\"85.59\"\n          r=\"153.78\"\n          gradientTransform=\"translate(0 25.56) scale(1 .7)\"\n          xlinkHref=\"#snoo-radial-gragient\"\n        />\n        <radialGradient\n          id=\"snoo-radial-gragient-4\"\n          cx=\"-6.01\"\n          cy=\"64.68\"\n          fx=\"-6.01\"\n          fy=\"64.68\"\n          r=\"12.85\"\n          gradientTransform=\"translate(81.08 27.26) scale(1.07 1.55)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop offset=\"0\" stopColor=\"#f60\" />\n          <stop offset=\".5\" stopColor=\"#ff4500\" />\n          <stop offset=\".7\" stopColor=\"#fc4301\" />\n          <stop offset=\".82\" stopColor=\"#f43f07\" />\n          <stop offset=\".92\" stopColor=\"#e53812\" />\n          <stop offset=\"1\" stopColor=\"#d4301f\" />\n        </radialGradient>\n        <radialGradient\n          id=\"snoo-radial-gragient-5\"\n          cx=\"-73.55\"\n          cy=\"64.68\"\n          fx=\"-73.55\"\n          fy=\"64.68\"\n          r=\"12.85\"\n          gradientTransform=\"translate(62.87 27.26) rotate(-180) scale(1.07 -1.55)\"\n          xlinkHref=\"#snoo-radial-gragient-4\"\n        />\n        <radialGradient\n          id=\"snoo-radial-gragient-6\"\n          cx=\"107.93\"\n          cy=\"166.96\"\n          fx=\"107.93\"\n          fy=\"166.96\"\n          r=\"45.3\"\n          gradientTransform=\"translate(0 57.4) scale(1 .66)\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop offset=\"0\" stopColor=\"#172e35\"></stop>\n          <stop offset=\".29\" stopColor=\"#0e1c21\"></stop>\n          <stop offset=\".73\" stopColor=\"#030708\"></stop>\n          <stop offset=\"1\" stopColor=\"#000\"></stop>\n        </radialGradient>\n        <radialGradient\n          id=\"snoo-radial-gragient-7\"\n          cx=\"147.88\"\n          cy=\"32.94\"\n          fx=\"147.88\"\n          fy=\"32.94\"\n          r=\"39.77\"\n          gradientTransform=\"translate(0 .54) scale(1 .98)\"\n          xlinkHref=\"#snoo-radial-gragient\"\n        />\n        <radialGradient\n          id=\"snoo-radial-gragient-8\"\n          cx=\"131.31\"\n          cy=\"73.08\"\n          fx=\"131.31\"\n          fy=\"73.08\"\n          r=\"32.6\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop offset=\".48\" stopColor=\"#7a9299\" />\n          <stop offset=\".67\" stopColor=\"#172e35\" />\n          <stop offset=\".75\" stopColor=\"#000\" />\n          <stop offset=\".82\" stopColor=\"#172e35\" />\n        </radialGradient>\n      </defs>\n      <path\n        className={redditStyles.snoo10}\n        d=\"m108,0h0C48.35,0,0,48.35,0,108h0c0,29.82,12.09,56.82,31.63,76.37l-20.57,20.57c-4.08,4.08-1.19,11.06,4.58,11.06h92.36s0,0,0,0c59.65,0,108-48.35,108-108h0C216,48.35,167.65,0,108,0Z\"\n      />\n      <circle\n        className={redditStyles.snoo1}\n        cx=\"169.22\"\n        cy=\"106.98\"\n        r=\"25.22\"\n      />\n      <circle className={redditStyles.snoo2} cx=\"46.78\" cy=\"106.98\" r=\"25.22\" />\n      <ellipse\n        className={redditStyles.snoo3}\n        cx=\"108.06\"\n        cy=\"128.64\"\n        rx=\"72\"\n        ry=\"54\"\n      />\n      <path\n        className={redditStyles.snoo4}\n        d=\"m86.78,123.48c-.42,9.08-6.49,12.38-13.56,12.38s-12.46-4.93-12.04-14.01c.42-9.08,6.49-15.02,13.56-15.02s12.46,7.58,12.04,16.66Z\"\n      />\n      <path\n        className={redditStyles.snoo7}\n        d=\"m129.35,123.48c.42,9.08,6.49,12.38,13.56,12.38s12.46-4.93,12.04-14.01c-.42-9.08-6.49-15.02-13.56-15.02s-12.46,7.58-12.04,16.66Z\"\n      />\n      <ellipse\n        className={redditStyles.snoo11}\n        cx=\"79.63\"\n        cy=\"116.37\"\n        rx=\"2.8\"\n        ry=\"3.05\"\n      />\n      <ellipse\n        className={redditStyles.snoo11}\n        cx=\"146.21\"\n        cy=\"116.37\"\n        rx=\"2.8\"\n        ry=\"3.05\"\n      />\n      <path\n        className={redditStyles.snoo5}\n        d=\"m108.06,142.92c-8.76,0-17.16.43-24.92,1.22-1.33.13-2.17,1.51-1.65,2.74,4.35,10.39,14.61,17.69,26.57,17.69s22.23-7.3,26.57-17.69c.52-1.23-.33-2.61-1.65-2.74-7.77-.79-16.16-1.22-24.92-1.22Z\"\n      />\n      <circle className={redditStyles.snoo8} cx=\"147.49\" cy=\"49.43\" r=\"17.87\" />\n      <path\n        className={redditStyles.snoo6}\n        d=\"m107.8,76.92c-2.14,0-3.87-.89-3.87-2.27,0-16.01,13.03-29.04,29.04-29.04,2.14,0,3.87,1.73,3.87,3.87s-1.73,3.87-3.87,3.87c-11.74,0-21.29,9.55-21.29,21.29,0,1.38-1.73,2.27-3.87,2.27Z\"\n      />\n      <path\n        className={redditStyles.snoo9}\n        d=\"m62.82,122.65c.39-8.56,6.08-14.16,12.69-14.16,6.26,0,11.1,6.39,11.28,14.33.17-8.88-5.13-15.99-12.05-15.99s-13.14,6.05-13.56,15.2c-.42,9.15,4.97,13.83,12.04,13.83.17,0,.35,0,.52,0-6.44-.16-11.3-4.79-10.91-13.2Z\"\n      />\n      <path\n        className={redditStyles.snoo9}\n        d=\"m153.3,122.65c-.39-8.56-6.08-14.16-12.69-14.16-6.26,0-11.1,6.39-11.28,14.33-.17-8.88,5.13-15.99,12.05-15.99,7.07,0,13.14,6.05,13.56,15.2.42,9.15-4.97,13.83-12.04,13.83-.17,0-.35,0-.52,0,6.44-.16,11.3-4.79,10.91-13.2Z\"\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "site/src/components/SectionQuotes/index.tsx",
    "content": "import clsx from 'clsx'\n\nimport { Quote } from './Quote'\nimport { quotes } from './quotes'\nimport styles from './styles.module.css'\n\nexport function SectionQuotes() {\n  return (\n    <section className={styles.quotesSection}>\n      <div className={clsx('container', styles.quotesContainer)}>\n        <h2>What the internet is saying</h2>\n        <p>Developers are loving Kysely for its simplicity and power.</p>\n        <div className={styles.quotesInnerContainer}>\n          {quotes.map((quote, index) => (\n            <Quote key={index} {...quote} />\n          ))}\n        </div>\n      </div>\n    </section>\n  )\n}\n"
  },
  {
    "path": "site/src/components/SectionQuotes/quotes.ts",
    "content": "import type { QuoteProps } from './Quote'\n\nexport const quotes: QuoteProps[] = [\n  {\n    authorName: 'Tim Griesser',\n    authorTitle: 'Knex.js creator, Cypress Staff Eng',\n    avatar: 'tgriesser',\n    link: 'https://github.com/kysely-org/kysely/issues/352#issue-1612115150',\n    text: \"👋 First just wanted to say this project looks awesome! Pretty close to what I wish Knex was if I started it now, with the affordances of modern TypeScript instead of 10 years ago when we were stuck in ES5 and Promises weren't even really an official language construct yet.\",\n  },\n  {\n    authorName: 'Orta Therox',\n    authorTitle: 'Ex-TypeScript team',\n    avatar: 'orta',\n    link: 'https://discord.com/channels/890118421587578920/890118421587578925/1037692748825903114',\n    text: \"👋 been using Kysely for a few days in Deno and Node, just wanted to say it's been going really well and it feels like a nice abstraction - kudos!\",\n  },\n  {\n    authorName: 'Niels Sandholt Busch',\n    authorTitle: 'Maersk SWE',\n    avatar: 'niels',\n    link: 'https://github.com/kysely-org/kysely/issues/320#issuecomment-2183966432',\n    text: 'We are using Kysely in production at Maersk inventory control!',\n  },\n  {\n    authorName: 'Lee \"leerob\" Robinson',\n    authorTitle: 'Cursor VP DX, Ex-Vercel',\n    avatar: 'leerob',\n    link: 'https://x.com/leeerob/status/1576929372811849730',\n    text: 'Type-safe SQL queries with PlanetScale and Kysely 😍',\n  },\n  {\n    authorName: 'Guðmundur Bjarni Olafsson',\n    authorTitle: 'Vercel Principal SWE, Ex-GitHub',\n    avatar: 'gudmundur',\n    link: 'https://x.com/gudmundur/status/1740075197179605250',\n    text: \"I made a strong recommendation internally for using Kysely for a greenfield service that's in the works. Looks very solid. 👌🏻\",\n  },\n  {\n    authorName: 'Marvin Hagemeister',\n    authorTitle: 'Preact core team, Deno SWE',\n    avatar: 'marvinh',\n    link: 'https://reddit.com/r/Deno/comments/1hvofl1/comment/mbbhmf1',\n    text: \"We're using Kysely as an ORM here at Deno. It's quite neat.\",\n  },\n  {\n    authorName: 'Søren Bramer Schmidt',\n    authorTitle: 'Prisma CEO',\n    avatar: 'soren',\n    link: 'https://x.com/sorenbs/status/1943688341657977035',\n    text: 'Kysely is great!',\n  },\n  {\n    authorName: 'Yusuke \"yusukebe\" Wada',\n    authorTitle: 'Hono creator, Cloudflare DevRel',\n    avatar: 'yusuke',\n    link: 'https://x.com/yusukebe/status/1581775103167066112',\n    text: 'Kysely is great. D1 will be great. This is great.',\n  },\n  {\n    authorName: 'Kevin \"Egoist\"',\n    authorTitle: 'tsup creator, ChatWise founder',\n    avatar: 'egoist',\n    link: 'https://x.com/localhost_5173/status/1863495153325130032',\n    text: 'Thank you kysely',\n  },\n  {\n    authorName: 'Julius Marminge',\n    authorTitle: 'tRPC core team, T3 Chat SWE',\n    avatar: 'julius',\n    link: 'https://x.com/jullerino/status/1676687249998598148',\n    text: 'Utterly astounded by how Kysely manages to make all of this typesafe. Seems like no matter how complex you get, it can infer it correctly.',\n  },\n  {\n    authorName: 'Sean Brydon',\n    authorTitle: 'Cal.com SWE',\n    avatar: 'sean',\n    link: 'https://github.com/kysely-org/kysely/issues/320#issuecomment-2990566802',\n    text: 'We are using Kysely for some of our more complex queries in Cal.com where we needed more control of the sql generated.',\n  },\n  {\n    authorName: 'Dax \"thdxr\" Raad',\n    authorTitle: 'SST & opencode core team',\n    avatar: 'daxraad',\n    link: 'https://x.com/thdxr/status/1566512393500463104',\n    text: \"really excited to see Kysely get more attention - been banging this drum for a while and we've integrated pretty deeply with it at SST incidentally its codebase remains the best Typescript codebase I have ever seen - worth poking around\",\n  },\n  {\n    authorName: 'Gal Schlezinger',\n    authorTitle: 'fnm creator, Vercel SWE',\n    avatar: 'gal',\n    link: 'https://x.com/galstar/status/1740049724810695135',\n    text: \"I love SQL, and I love migrations, most tools don't provide good migration tools and fine grained control like Kysely which is why it's my favorite.\",\n  },\n  {\n    authorName: 'Mathieu Acthernoene',\n    authorTitle: 'react-native-edge-to-edge creator',\n    avatar: 'mathieu',\n    link: 'https://x.com/zoontek/status/1915730955890761827',\n    text: 'Used in prod here, highly recommended',\n  },\n  {\n    authorName: 'Ben Holmes',\n    authorTitle: 'Warp SWE, Ex-Astro',\n    avatar: 'benholmes',\n    link: 'https://x.com/BHolmesDev/status/1683505989465645056',\n    text: 'I really like Prisma for schemas and Kysely for querying. Drizzle feels... younger for schemas, but also quite nice',\n  },\n  {\n    authorName: 'Bereket Engida',\n    authorTitle: 'better-auth creator',\n    avatar: 'bekacru',\n    link: 'https://x.com/imbereket/status/1691066440294481920',\n    text: \"I don't think they have similar goals from what I see. Drizzle is more dedicated into marketing and having every user possible like prisma but kysely kinda just don't care about that for most part. And in my experience prisma + kysely is better than drizzle.\",\n  },\n  {\n    authorName: 'Peter Pistorius',\n    authorTitle: 'RedwoodJS creator, Ex-Snaplet',\n    avatar: 'peter',\n    link: 'https://x.com/appfactory/status/1953009209185800324',\n    text: \"Today I'll be adding persistence to Machinen using RedwookSDK's Durable Object database integration: It uses kysely under the hood. Typesafety is directly provided by migrations.\",\n  },\n  {\n    authorName: 'Harminder Virk',\n    authorTitle: 'AdonisJS creator',\n    avatar: 'harminder',\n    link: 'https://x.com/AmanVirk1/status/1753348028139024628',\n    text: 'If not Lucid, Kysely is what I would recommend everyone use. It presents itself as a type-safe SQL query builder and delivers 100% on that promise.',\n  },\n  {\n    authorName: 'Catalin Pit',\n    authorTitle: 'Documenso SWE',\n    avatar: 'catalin',\n    link: 'https://x.com/catalinmpit/status/1837850745242104318',\n    text: 'Kysely is fantastic! We use it at @documenso with Prisma.',\n  },\n  {\n    authorName: '\"pilcrow\"',\n    authorTitle: 'Lucia creator',\n    avatar: 'pilcrowonpaper',\n    link: 'https://x.com/pilcrowonpaper/status/1675135710981165057',\n    text: \"Ok, so I'm not a big fan of Drizzle. I don't like how I have to import everything when declaring schemas and queries, and I just prefer the simplicity and the overall API of Kysely.\",\n  },\n  {\n    authorName: 'Theo \"t3dotgg\" Browne',\n    authorTitle: 'Uploadthing creator, T3 Chat CEO',\n    avatar: 'theo',\n    link: 'https://x.com/t3dotgg/status/1649539910037311495',\n    text: 'kysely is dope too. Drizzle and kysely are the frontrunners for \"new db tools that really understand JS needs\" atm',\n  },\n  {\n    authorName: 'Nicholas Griffin',\n    authorTitle: 'sqs-consumer maintainer, BBC SWE',\n    avatar: 'nicholas',\n    link: 'https://x.com/ngriffin_uk/status/1599891725404676096',\n    text: \"I don't actually like prisma that much, I prefer Kysely, not an ORM though.\",\n  },\n  {\n    authorName: 'Shoubhit \"nexxel\" Dash',\n    authorTitle: 'create-t3-app author',\n    avatar: 'nexxel',\n    link: 'https://x.com/nexxeln/status/1676975946606452737',\n    text: 'kysely is great btw',\n  },\n  {\n    authorName: 'Guga Guichard',\n    authorTitle: 'string-ts creator, Seasoned Partner',\n    avatar: 'guga',\n    link: 'https://x.com/gugaguichard/status/1844896761468551457',\n    text: \"I've been seeing a lot of discussions about ORMs vs raw SQL. What about strongly typed SQL query builders? Kysely is in the sweet spot! Best DX with total freedom I've seen in decades.\",\n  },\n  {\n    authorName: 'Johan Eliasson',\n    authorTitle: 'Gazella CTO, Nhost founder',\n    avatar: 'johan',\n    link: 'https://x.com/elitasson/status/1642090379066449920',\n    text: \"Instead of Prisma, I'm testing Kysely, Kysely Codegen, and Atlas. Works great.\",\n  },\n  {\n    authorName: 'Samuel Bodin',\n    authorTitle: 'Nango SWE, Ex-Algolia',\n    avatar: 'samuel',\n    link: 'https://x.com/samdotb/status/1943598629559615668',\n    text: 'Im currently in love with Kysely, it has found the perfect balance/API imo',\n  },\n  {\n    authorName: 'Endel Dreyer',\n    authorTitle: 'Colyseus creator',\n    avatar: 'endel',\n    link: 'https://x.com/endel/status/1927811324127400017',\n    text: 'i just use postgres + kysely and old school migrations as needed',\n  },\n  {\n    authorName: 'Alberto \"gimenete\" Gimeno',\n    authorTitle: 'Stripe SWE, Ex-GitHub',\n    avatar: 'alberto',\n    link: 'https://x.com/gimenete/status/1653121152854765569',\n    text: \"I'm a happy Kysely user. It's great to see that the code I'm writing now can work with serverless PostgreSQL now!\",\n  },\n  {\n    authorName: 'R. Alex Anderson',\n    authorTitle: 'Thorium Nova creator',\n    avatar: 'alexanderson',\n    link: 'https://x.com/ralex1993/status/1677632989260390403',\n    text: 'Shout out to Kysely for adding extensive JSDoc comments above the methods. It makes it much easier to figure out how to use it the way I want without having to dig into the docs. (though the docs are vv good too)',\n  },\n  {\n    authorName: 'Mehul Mohan',\n    authorTitle: 'Fermion founder',\n    avatar: 'mehul',\n    link: 'https://x.com/mehulmpt/status/1650480912759685120',\n    text: 'We went with query builder because we did not have more time to waste on ORMs. ORMs might be great but we have the technical capability to pull off just using a query builder. However, we type safety and sanitization for DX and security was a must - hence Kysely.',\n  },\n  {\n    authorName: 'Sam Cook',\n    authorTitle: 'River creator, Gamma.io SWE',\n    avatar: 'samcook',\n    link: 'https://x.com/sjc5_/status/1623210443874639873',\n    text: 'Kysely is amazing.',\n  },\n  {\n    authorName: 'Alisson \"thelinuxlich\" C.Agiani',\n    authorTitle: 'Mutano creator',\n    avatar: 'sommelier',\n    link: 'https://x.com/solinvictvs/status/1615549659115655169',\n    text: 'Kysely is superior and with each release gets even more awesome',\n  },\n  {\n    authorName: 'Marvin',\n    authorTitle: 'Indie Hacker',\n    avatar: 'marvin',\n    link: 'https://x.com/marvr_/status/1833070144064479434',\n    text: \"I've been saying it many times already, but it's probably one of the best additions to my tech stack. I enjoy writing SQL since I know Kysely 😆\",\n  },\n  {\n    authorName: 'Jiří \"Capaj\" Špác',\n    authorTitle: 'Langtail SWE',\n    avatar: 'capaj',\n    link: 'https://x.com/capajj/status/1824003221397885343',\n    text: 'Kysely is awesome',\n  },\n]\n"
  },
  {
    "path": "site/src/components/SectionQuotes/reddit.module.css",
    "content": ".snoo1 {\n  fill: url(#snoo-radial-gragient) white;\n}\n\n.snoo1,\n.snoo2,\n.snoo3,\n.snoo4,\n.snoo5,\n.snoo6,\n.snoo7,\n.snoo8,\n.snoo9,\n.snoo10,\n.snoo11 {\n  stroke-width: 0px;\n}\n\n.snoo2 {\n  fill: url(#snoo-radial-gragient-2) white;\n}\n\n.snoo3 {\n  fill: url(#snoo-radial-gragient-3) white;\n}\n\n.snoo4 {\n  fill: url(#snoo-radial-gragient-4) #fc4301;\n}\n\n.snoo5 {\n  fill: url(#snoo-radial-gragient-6) black;\n}\n\n.snoo6 {\n  fill: url(#snoo-radial-gragient-8) black;\n}\n\n.snoo7 {\n  fill: url(#snoo-radial-gragient-5) #fc4301;\n}\n\n.snoo8 {\n  fill: url(#snoo-radial-gragient-7) white;\n}\n\n.snoo9 {\n  fill: #842123;\n}\n\n.snoo10 {\n  fill: #ff4500;\n}\n\n.snoo11 {\n  fill: #ffc49c;\n}\n"
  },
  {
    "path": "site/src/components/SectionQuotes/styles.module.css",
    "content": ".quoteContainer {\n  align-items: flex-start;\n  background-color: white;\n  border-radius: 8px;\n  display: flex;\n  flex: 0 1 300px;\n  flex-direction: column;\n  gap: 8px;\n  padding: 16px;\n  position: relative;\n  text-decoration: none;\n}\n\n[data-theme='dark'] .quoteContainer {\n  background-color: var(--gray-12);\n}\n\n.quoteInnerContainer {\n  display: flex;\n  gap: 8px;\n}\n\n.quoteHeader {\n  align-items: flex-start;\n  display: flex;\n  flex-direction: column;\n}\n\n.quoteTitle,\n.quoteSubtitle {\n  color: var(--gray-11);\n}\n\n[data-theme='dark'] .quoteTitle,\n[data-theme='dark'] .quoteSubtitle {\n  color: var(--gray-9);\n}\n\n.quoteText {\n  color: var(--gray-12);\n  text-align: left;\n}\n\n[data-theme='dark'] .quoteText {\n  color: var(--gray-6);\n}\n\n.quotesSection {\n  background: radial-gradient(circle, var(--sky-4) 0%, white 65%);\n  display: grid;\n  place-items: center;\n}\n\n[data-theme='dark'] .quotesSection {\n  background: radial-gradient(circle, var(--blue-12) 0%, var(--gray-12) 65%);\n}\n\n.quotesContainer {\n  text-align: center;\n}\n\n.quotesInnerContainer {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 16px;\n  justify-content: center;\n}\n\n.icon {\n  bottom: 18px;\n  height: 16px;\n  position: absolute;\n  right: 18px;\n  width: 16px;\n}\n\n[data-theme='dark'] .darkIcon {\n  fill: white;\n}\n"
  },
  {
    "path": "site/src/components/playground-example-types.ts",
    "content": "// THIS FILE IS GENERATED BY `scripts/generate-site-examples.js`\n// DO NOT EDIT THIS FILE DIRECTLY\nexport const GENERATED_PLAYGROUND_EXAMPLE_TYPES = `import type {\n  ColumnType,\n  Generated,\n  GeneratedAlways,\n  Insertable,\n  Kysely,\n  Selectable,\n  SqlBool,\n  Updateable,\n} from 'kysely'\n\nexport interface Database {\n  audit: AuditTable\n  person: PersonTable\n  person_backup: PersonTable\n  pet: PetTable\n  toy: ToyTable\n  wine: WineTable\n  wine_stock_change: WineStockChangeTable\n}\n\ninterface AuditTable {\n  id: Generated<number>\n  action: string\n}\n\ninterface PersonTable {\n  id: Generated<number>\n  address: { city: string } | null\n  age: number | null\n  birthdate: ColumnType<Date | null, string | null | undefined, string | null>\n  created_at: GeneratedAlways<Date>\n  deleted_at: ColumnType<Date | null, string | null | undefined, string | null>\n  experience: { role: string }[] | null\n  first_name: string\n  gender: 'male' | 'female' | 'other' | null\n  has_pets: Generated<'Y' | 'N'>\n  last_name: string | null\n  middle_name: string | null\n  nicknames: string[] | null\n  nullable_column: string | null\n  profile: {\n    addresses: { city: string }[]\n    website: { url: string }\n  } | null\n  updated_at: ColumnType<Date | null, string | null | undefined, string | null>\n  marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n}\n\ninterface PetTable {\n  id: Generated<number>\n  created_at: GeneratedAlways<Date>\n  is_favorite: Generated<SqlBool>\n  name: string\n  owner_id: number\n  species: Species\n}\n\ninterface ToyTable {\n  id: Generated<number>\n  name: string\n  pet_id: number\n  price: number\n}\n\ninterface WineTable {\n  id: Generated<number>\n  name: string\n  stock: number\n}\n\ninterface WineStockChangeTable {\n  id: Generated<number>\n  stock_delta: number\n  wine_name: string\n}\n\nexport type Person = Selectable<PersonTable>\nexport type NewPerson = Insertable<PersonTable>\nexport type PersonUpdate = Updateable<PersonTable>\nexport type Pet = Selectable<PetTable>\nexport type NewPet = Insertable<PetTable>\nexport type PetUpdate = Updateable<PetTable>\nexport type Species = 'dog' | 'cat' | 'hamster'\n\ndeclare global {\n  // @ts-ignore\n  export class Buffer {\n    static isBuffer(obj: unknown): obj is { length: number }\n    static compare(a: Buffer, b: Buffer): number\n  }\n  export const db: Kysely<Database>\n  export function functionThatExpectsPersonWithNonNullValue(\n    person: Person & { nullable_column: string },\n  ): void\n}\n`;"
  },
  {
    "path": "site/src/css/custom.css",
    "content": "/**\n * Any CSS included here will be global. The classic template\n * bundles Infima by default. Infima is a CSS framework designed to\n * work well for content-centric websites.\n */\n\n/* You can override the default Infima variables here. */\n:root {\n  --ifm-color-primary: var(--sky-9);\n  --ifm-color-primary-dark: var(--sky-10);\n  --ifm-color-primary-darker: var(--sky-11);\n  --ifm-color-primary-darkest: var(--sky-12);\n  --ifm-color-primary-light: var(--sky-8);\n  --ifm-color-primary-lighter: var(--sky-7);\n  --ifm-color-primary-lightest: var(--sky-6);\n  --ifm-footer-background-color: var(--sky-12);\n  --ifm-code-font-size: 95%;\n  --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);\n  --ifm-button-font-weight: 500;\n  --shadow-color: 0deg 0% 0%;\n  --shadow-elevation-low:\n    -0.1px 0.5px 0.6px hsl(var(--shadow-color) / 0.1),\n    -0.2px 0.8px 0.9px -1.2px hsl(var(--shadow-color) / 0.1),\n    -0.6px 2px 2.3px -2.5px hsl(var(--shadow-color) / 0.1);\n  --shadow-elevation-medium:\n    -0.1px 0.5px 0.6px hsl(var(--shadow-color) / 0.11),\n    -0.5px 1.7px 2px -0.8px hsl(var(--shadow-color) / 0.11),\n    -1.2px 4.2px 4.9px -1.7px hsl(var(--shadow-color) / 0.11),\n    -3px 10.1px 11.9px -2.5px hsl(var(--shadow-color) / 0.11);\n  --shadow-elevation-high:\n    -0.1px 0.5px 0.6px hsl(var(--shadow-color) / 0.1),\n    -0.9px 3px 3.5px -0.4px hsl(var(--shadow-color) / 0.1),\n    -1.6px 5.5px 6.4px -0.7px hsl(var(--shadow-color) / 0.1),\n    -2.6px 9.1px 10.6px -1.1px hsl(var(--shadow-color) / 0.1),\n    -4.2px 14.5px 17px -1.4px hsl(var(--shadow-color) / 0.1),\n    -6.6px 22.6px 26.5px -1.8px hsl(var(--shadow-color) / 0.1),\n    -10px 34.4px 40.3px -2.1px hsl(var(--shadow-color) / 0.1),\n    -14.8px 50.6px 59.3px -2.5px hsl(var(--shadow-color) / 0.1);\n}\n\n/* remove default theme max-width in examples content */\n:root [class^='col docItemCol_'] {\n  max-width: unset !important;\n}\n\n[data-theme='dark'] {\n  --ifm-color-primary: var(--sky-9);\n  --ifm-color-primary-dark: var(--sky-10);\n  --ifm-color-primary-darker: var(--sky-11);\n  --ifm-color-primary-darkest: var(--sky-12);\n  --ifm-color-primary-light: var(--sky-6);\n  --ifm-color-primary-lighter: var(--sky-4);\n  --ifm-color-primary-lightest: var(--sky-2);\n  --ifm-footer-background-color: var(--sky-12);\n}\n\n[data-theme='light'] .footer {\n  background-image: linear-gradient(\n    180deg,\n    hsl(0deg 0% 100%) 0%,\n    hsl(227deg 10% 98%) 40%,\n    hsl(226deg 19% 97%) 58%,\n    hsl(224deg 28% 96%) 69%,\n    hsl(222deg 36% 95%) 77%,\n    hsl(220deg 45% 94%) 83%,\n    hsl(219deg 54% 93%) 89%,\n    hsl(216deg 65% 93%) 93%,\n    hsl(214deg 80% 93%) 97%,\n    hsl(211deg 100% 93%) 100%\n  );\n  --ifm-footer-title-color: var(--ifm-color-black);\n  --ifm-footer-link-color: var(--gray-12);\n}\n\n[data-theme='dark'] .footer {\n  background-image: linear-gradient(\n    180deg,\n    hsl(0deg 0% 9%) 0%,\n    hsl(227deg 10% 10%) 40%,\n    hsl(226deg 19% 11%) 58%,\n    hsl(224deg 28% 12%) 69%,\n    hsl(222deg 36% 13%) 77%,\n    hsl(220deg 45% 14%) 83%,\n    hsl(219deg 54% 15%) 89%,\n    hsl(216deg 65% 15%) 93%,\n    hsl(214deg 80% 15%) 97%,\n    hsl(211deg 100% 15%) 100%\n  );\n}\n\n.navbar__title {\n  text-transform: uppercase;\n  font-weight: 300;\n}\n\n.button {\n  box-shadow: var(--shadow-elevation-medium);\n}\n"
  },
  {
    "path": "site/src/pages/index.module.css",
    "content": ".heroBanner {\n  padding: 4rem 0;\n  text-align: center;\n  position: relative;\n  overflow: hidden;\n  min-height: calc(100vh - var(--ifm-navbar-height));\n\n  position: relative;\n  background: linear-gradient(\n    315deg,\n    var(--sky-7) 3%,\n    var(--blue-7) 38%,\n    var(--sky-7) 68%,\n    var(--blue-7) 98%\n  );\n  animation: gradient 95s ease infinite;\n  background-size: 400% 400%;\n  background-attachment: fixed;\n}\n\n@keyframes bounce {\n  0% {\n    transform: translateX(-50%) translateY(0);\n  }\n  50% {\n    transform: translateX(-50%) translateY(-10px);\n  }\n  100% {\n    transform: translateX(-50%) translateY(0);\n  }\n}\n\n.heroTitle {\n  font-size: 90px;\n  font-weight: 200;\n  color: var(--sky-12);\n}\n\n.heroSubtitle {\n  font-size: 24px;\n  font-weight: 300;\n  color: var(--sky-12);\n  line-height: 1.2;\n}\n\n.buttons {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n@keyframes gradient {\n  0% {\n    background-position: 0% 0%;\n  }\n  50% {\n    background-position: 100% 100%;\n  }\n  100% {\n    background-position: 0% 0%;\n  }\n}\n\n.wave {\n  /* pause the animation */\n  animation-play-state: paused;\n  background: rgb(255 255 255 / 10%);\n  border-radius: 1000%;\n  position: absolute;\n  width: 400vw;\n  height: 400vh;\n  animation: wave 200s 0s linear infinite;\n  transform: translate3d(0, 0, 0);\n  opacity: 0.8;\n  top: 20vh;\n  left: 20vw;\n}\n\n.wave:nth-of-type(2) {\n  top: 0vh;\n  left: 0vw;\n  animation-duration: 190s;\n}\n\n.wave:nth-of-type(3) {\n  top: -20vh;\n  left: -20vw;\n  animation-duration: 180s;\n}\n\n.wave:nth-of-type(4) {\n  top: -40vh;\n  left: -40vw;\n  animation-duration: 170s;\n}\n\n.wave:nth-of-type(5) {\n  top: -60vh;\n  left: -60vw;\n  animation-duration: 160s;\n}\n\n@keyframes wave {\n  2% {\n    transform: translateX(0%);\n  }\n\n  25% {\n    transform: translateX(-10%);\n  }\n\n  50% {\n    transform: translateX(0%);\n  }\n\n  75% {\n    transform: translateX(10%);\n  }\n\n  100% {\n    transform: translateX(0%);\n  }\n}\n\n.playground {\n  border-radius: 8px;\n  border: 1px solid var(--gray-11);\n  height: 100%;\n  overflow: hidden;\n  padding: 0;\n  width: 100%;\n}\n\n/* Prevent mobile browser from scrolling to iframe on page load */\n@media (max-width: 768px) {\n  .playground {\n    overflow-anchor: none;\n    /* Make iframe not focusable but still interactive */\n    pointer-events: auto;\n  }\n\n  .playground:focus {\n    outline: none;\n  }\n}\n\n.playgroundContainer {\n  align-items: center;\n  border: 0;\n  display: flex;\n  flex-direction: column;\n  height: calc(100vh - var(--ifm-navbar-height));\n  overflow: hidden;\n  padding: 0;\n  padding-bottom: 40px;\n  padding-top: 60px;\n  width: 100%;\n}\n\n[data-theme='dark'] .playgroundSection {\n  background: var(--gray-12);\n}\n\n.examplesCTASection {\n  background: radial-gradient(circle, var(--sky-4) 0%, white 20%);\n  display: grid;\n  place-items: center;\n}\n\n[data-theme='dark'] .examplesCTASection {\n  background: radial-gradient(circle, var(--blue-12) 0%, var(--gray-12) 20%);\n}\n\n.examplesCTAContainer {\n  align-items: center;\n  display: flex;\n  flex-direction: column;\n  max-width: 460px;\n  padding: 128px 0;\n  text-align: center;\n}\n\n.examplesCTA {\n  display: flex;\n  gap: 8px;\n}\n"
  },
  {
    "path": "site/src/pages/index.tsx",
    "content": "import React, { JSX } from 'react'\nimport { useColorMode } from '@docusaurus/theme-common'\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext'\nimport Layout from '@theme/Layout'\nimport clsx from 'clsx'\nimport { useEffect, useState } from 'react'\n\nimport { SectionFeatures } from '../components/SectionFeatures'\nimport { DemoVideo } from '../components/DemoVideo'\nimport { SectionQuotes } from '../components/SectionQuotes'\nimport styles from './index.module.css'\n\nfunction HomepageHeader() {\n  const { siteConfig } = useDocusaurusContext()\n  return (\n    <header className={clsx('hero', styles.heroBanner, 'dark-theme')}>\n      <div className={styles.wave} />\n      <div className={styles.wave} />\n      <div className={styles.wave} />\n      <div className={styles.wave} />\n      <div className={styles.wave} />\n      <div\n        className=\"container\"\n        style={{\n          display: 'flex',\n          flexDirection: 'column',\n          alignItems: 'center',\n          justifyContent: 'center',\n          gap: '32px',\n          zIndex: 1,\n        }}\n      >\n        <div style={{ display: 'flex', flexDirection: 'column' }}>\n          <h1 className={styles.heroTitle}>{siteConfig.title}</h1>\n          <p className={styles.heroSubtitle}>\n            The type-safe SQL <br />\n            query builder for TypeScript\n          </p>\n          <span style={{ display: 'flex', flexDirection: 'row', gap: 8 }}>\n            <a\n              href=\"/docs/getting-started\"\n              className=\"button button--primary button--md button--block\"\n              style={{\n                background: 'var(--gray-12)',\n                color: 'var(--gray-1)',\n                borderColor: 'var(--gray-12)',\n              }}\n            >\n              Getting started\n            </a>\n            <a\n              href=\"https://github.com/kysely-org/kysely\"\n              className=\"button button--secondary button--md button--block\"\n            >\n              View on GitHub\n            </a>\n          </span>\n        </div>\n\n        <DemoVideo />\n      </div>\n    </header>\n  )\n}\n\nexport default function Home(): JSX.Element {\n  const { siteConfig } = useDocusaurusContext()\n\n  return (\n    <Layout title={siteConfig.title}>\n      <div className={styles.siteWrapper}>\n        <HomepageHeader />\n      </div>\n      <main>\n        <SectionFeatures />\n\n        <SectionQuotes />\n\n        <SectionPlayground />\n\n        <SectionExamplesCTA />\n      </main>\n    </Layout>\n  )\n}\n\nconst STACKBLITZ_URL = 'https://stackblitz.com/edit/react-ts-pppzf5'\nconst STACKBLITZ_PARAMS = new URLSearchParams({\n  ctl: '1',\n  embed: '1',\n  file: 'playground.ts',\n  hidedevtools: '1',\n  hideExplorer: '1',\n  hideNavigation: '1',\n  showSidebar: '0',\n})\n\nfunction SectionPlayground() {\n  const { colorMode } = useColorMode()\n\n  const [src, setSrc] = useState(STACKBLITZ_URL)\n\n  useEffect(() => {\n    STACKBLITZ_PARAMS.set('theme', colorMode)\n\n    setSrc(`${STACKBLITZ_URL}?${STACKBLITZ_PARAMS}`)\n  }, [colorMode])\n\n  return (\n    <section className={styles.playgroundSection}>\n      <div className={clsx('container', styles.playgroundContainer)}>\n        <h2>Try it out for yourself!</h2>\n        <p>\n          Modify the query on the left and view the generated SQL on the right.\n        </p>\n        <iframe\n          allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n          className={styles.playground}\n          sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n          src={src}\n          tabIndex={-1}\n          title=\"Kysely Demo\"\n          loading=\"lazy\"\n        />\n      </div>\n    </section>\n  )\n}\n\nfunction SectionExamplesCTA() {\n  return (\n    <section className={styles.examplesCTASection}>\n      <div className={styles.examplesCTAContainer}>\n        <h2>Looking for code examples?</h2>\n        <p>\n          From finding a single record to complex joins, our docs have examples\n          to get you started quickly.\n        </p>\n        <span className={styles.examplesCTA}>\n          <a\n            className=\"button button--primary button--lg\"\n            href=\"/docs/category/examples\"\n            style={{ width: '220px' }}\n          >\n            Jump right in\n          </a>\n        </span>\n      </div>\n    </section>\n  )\n}\n"
  },
  {
    "path": "site/static/.nojekyll",
    "content": ""
  },
  {
    "path": "site/tsconfig.json",
    "content": "{\n  // This file is not used in compilation. It is here just for a nice editor experience.\n  \"extends\": \"@docusaurus/tsconfig\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"resolveJsonModule\": true,\n    \"strict\": true\n  }\n}\n"
  },
  {
    "path": "src/dialect/database-introspector.ts",
    "content": "/**\n * An interface for getting the database metadata (names of the tables and columns etc.)\n */\nexport interface DatabaseIntrospector {\n  /**\n   * Get schema metadata.\n   */\n  getSchemas(): Promise<SchemaMetadata[]>\n\n  /**\n   * Get tables and views metadata.\n   */\n  getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>\n\n  /**\n   * Get the database metadata such as table and column names.\n   *\n   * @deprecated Use getTables() instead.\n   */\n  getMetadata(options?: DatabaseMetadataOptions): Promise<DatabaseMetadata>\n}\n\nexport interface DatabaseMetadataOptions {\n  /**\n   * If this is true, the metadata contains the internal kysely tables\n   * such as the migration tables.\n   */\n  withInternalKyselyTables: boolean\n}\n\nexport interface SchemaMetadata {\n  readonly name: string\n}\n\nexport interface DatabaseMetadata {\n  /**\n   * The tables and views found in the database.\n   * The propery isView can be used to tell them apart.\n   */\n  readonly tables: TableMetadata[]\n}\n\nexport interface TableMetadata {\n  readonly name: string\n  readonly isView: boolean\n  readonly columns: ColumnMetadata[]\n  readonly schema?: string\n}\n\nexport interface ColumnMetadata {\n  readonly name: string\n\n  /**\n   * The data type of the column as reported by the database.\n   *\n   * NOTE: This value is whatever the database engine returns and it will be\n   *       different on different dialects even if you run the same migrations.\n   *       For example `integer` datatype in a migration will produce `int4`\n   *       on PostgreSQL, `INTEGER` on SQLite and `int` on MySQL.\n   */\n  readonly dataType: string\n\n  /**\n   * The schema this column's data type was created in.\n   */\n  readonly dataTypeSchema?: string\n\n  readonly isAutoIncrementing: boolean\n  readonly isNullable: boolean\n  readonly hasDefaultValue: boolean\n  readonly comment?: string\n}\n"
  },
  {
    "path": "src/dialect/dialect-adapter-base.ts",
    "content": "import type { Kysely } from '../kysely.js'\nimport type { DialectAdapter, MigrationLockOptions } from './dialect-adapter.js'\n\n/**\n * A basic implementation of `DialectAdapter` with sensible default values.\n * Third-party dialects can extend this instead of implementing the `DialectAdapter`\n * interface from scratch. That way all new settings will get default values when\n * they are added and there will be less breaking changes.\n */\nexport abstract class DialectAdapterBase implements DialectAdapter {\n  get supportsCreateIfNotExists(): boolean {\n    return true\n  }\n\n  get supportsTransactionalDdl(): boolean {\n    return false\n  }\n\n  get supportsReturning(): boolean {\n    return false\n  }\n\n  get supportsOutput(): boolean {\n    return false\n  }\n\n  abstract acquireMigrationLock(\n    db: Kysely<any>,\n    options: MigrationLockOptions,\n  ): Promise<void>\n\n  abstract releaseMigrationLock(\n    db: Kysely<any>,\n    options: MigrationLockOptions,\n  ): Promise<void>\n}\n"
  },
  {
    "path": "src/dialect/dialect-adapter.ts",
    "content": "import type { Kysely } from '../kysely.js'\n\n/**\n * A `DialectAdapter` encapsulates all differences between dialects outside\n * of `Driver` and `QueryCompiler`.\n *\n * For example, some databases support transactional DDL and therefore we want\n * to run migrations inside a transaction, while other databases don't support\n * it. For that there's a `supportsTransactionalDdl` boolean in this interface.\n */\nexport interface DialectAdapter {\n  /**\n   * Whether or not this dialect supports `if not exists` in creation of tables/schemas/views/etc.\n   *\n   * If this is false, Kysely's internal migrations tables and schemas are created\n   * without `if not exists` in migrations. This is not a problem if the dialect\n   * supports transactional DDL.\n   */\n  readonly supportsCreateIfNotExists: boolean\n\n  /**\n   * Whether or not this dialect supports transactional DDL.\n   *\n   * If this is true, migrations are executed inside a transaction.\n   */\n  readonly supportsTransactionalDdl: boolean\n\n  /**\n   * Whether or not this dialect supports the `returning` in inserts\n   * updates and deletes.\n   */\n  readonly supportsReturning: boolean\n\n  /**\n   * Whether or not this dialect supports the `output` clause in inserts\n   * updates and deletes.\n   */\n  readonly supportsOutput?: boolean\n\n  /**\n   * This method is used to acquire a lock for the migrations so that\n   * it's not possible for two migration operations to run in parallel.\n   *\n   * Most dialects have explicit locks that can be used, like advisory locks\n   * in PostgreSQL and the get_lock function in MySQL.\n   *\n   * If the dialect doesn't have explicit locks the {@link MigrationLockOptions.lockTable}\n   * created by Kysely can be used instead. You can access it through the `options` object.\n   * The lock table has two columns `id` and `is_locked` and there's only one row in the table\n   * whose id is {@link MigrationLockOptions.lockRowId}. `is_locked` is an integer. Kysely\n   * takes care of creating the lock table and inserting the one single row to it before this\n   * method is executed. If the dialect supports schemas and the user has specified a custom\n   * schema in their migration settings, the options object also contains the schema name in\n   * {@link MigrationLockOptions.lockTableSchema}.\n   *\n   * Here's an example of how you might implement this method for a dialect that doesn't\n   * have explicit locks but supports `FOR UPDATE` row locks and transactional DDL:\n   *\n   * ```ts\n   * import { DialectAdapterBase, type MigrationLockOptions, Kysely } from 'kysely'\n   *\n   * export class MyAdapter extends DialectAdapterBase {\n   *   override async acquireMigrationLock(\n   *     db: Kysely<any>,\n   *     options: MigrationLockOptions\n   *   ): Promise<void> {\n   *     const queryDb = options.lockTableSchema\n   *       ? db.withSchema(options.lockTableSchema)\n   *       : db\n   *\n   *     // Since our imaginary dialect supports transactional DDL and has\n   *     // row locks, we can simply take a row lock here and it will guarantee\n   *     // all subsequent calls to this method from other transactions will\n   *     // wait until this transaction finishes.\n   *     await queryDb\n   *       .selectFrom(options.lockTable)\n   *       .selectAll()\n   *       .where('id', '=', options.lockRowId)\n   *       .forUpdate()\n   *       .execute()\n   *   }\n   *\n   *   override async releaseMigrationLock() {\n   *     // noop\n   *   }\n   * }\n   * ```\n   *\n   * If `supportsTransactionalDdl` is `true` then the `db` passed to this method\n   * is a transaction inside which the migrations will be executed. Otherwise\n   * `db` is a single connection (session) that will be used to execute the\n   * migrations.\n   */\n  acquireMigrationLock(\n    db: Kysely<any>,\n    options: MigrationLockOptions,\n  ): Promise<void>\n\n  /**\n   * Releases the migration lock. See {@link acquireMigrationLock}.\n   *\n   * If `supportsTransactionalDdl` is `true` then the `db` passed to this method\n   * is a transaction inside which the migrations were executed. Otherwise `db`\n   * is a single connection (session) that was used to execute the migrations\n   * and the `acquireMigrationLock` call.\n   */\n  releaseMigrationLock(\n    db: Kysely<any>,\n    options: MigrationLockOptions,\n  ): Promise<void>\n}\n\nexport interface MigrationLockOptions {\n  /**\n   * The name of the migration lock table.\n   */\n  readonly lockTable: string\n\n  /**\n   * The id of the only row in the migration lock table.\n   */\n  readonly lockRowId: string\n\n  /**\n   * The schema in which the migration lock table lives. This is only\n   * defined if the user has specified a custom schema in the migration\n   * settings.\n   */\n  readonly lockTableSchema?: string\n}\n"
  },
  {
    "path": "src/dialect/dialect.ts",
    "content": "import type { Driver } from '../driver/driver.js'\nimport type { Kysely } from '../kysely.js'\nimport type { QueryCompiler } from '../query-compiler/query-compiler.js'\nimport type { DatabaseIntrospector } from './database-introspector.js'\nimport type { DialectAdapter } from './dialect-adapter.js'\n\n/**\n * A Dialect is the glue between Kysely and the underlying database engine.\n *\n * See the built-in {@link PostgresDialect} as an example of a dialect.\n * Users can implement their own dialects and use them by passing it\n * in the {@link KyselyConfig.dialect} property.\n */\nexport interface Dialect {\n  /**\n   * Creates a driver for the dialect.\n   */\n  createDriver(): Driver\n\n  /**\n   * Creates a query compiler for the dialect.\n   */\n  createQueryCompiler(): QueryCompiler\n\n  /**\n   * Creates an adapter for the dialect.\n   */\n  createAdapter(): DialectAdapter\n\n  /**\n   * Creates a database introspector that can be used to get database metadata\n   * such as the table names and column names of those tables.\n   *\n   * `db` never has any plugins installed. It's created using\n   * {@link Kysely.withoutPlugins}.\n   */\n  createIntrospector(db: Kysely<any>): DatabaseIntrospector\n}\n"
  },
  {
    "path": "src/dialect/mssql/mssql-adapter.ts",
    "content": "import type { Kysely } from '../../kysely.js'\nimport { DEFAULT_MIGRATION_TABLE } from '../../migration/migrator.js'\nimport { sql } from '../../raw-builder/sql.js'\nimport { DialectAdapterBase } from '../dialect-adapter-base.js'\n\nexport class MssqlAdapter extends DialectAdapterBase {\n  override get supportsCreateIfNotExists(): boolean {\n    return false\n  }\n\n  override get supportsTransactionalDdl(): boolean {\n    return true\n  }\n\n  override get supportsOutput(): boolean {\n    return true\n  }\n\n  override async acquireMigrationLock(db: Kysely<any>): Promise<void> {\n    // Acquire a transaction-level exclusive lock on the migrations table.\n    // https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql?view=sql-server-ver16\n    await sql`exec sp_getapplock @DbPrincipal = ${sql.lit(\n      'dbo',\n    )}, @Resource = ${sql.lit(DEFAULT_MIGRATION_TABLE)}, @LockMode = ${sql.lit(\n      'Exclusive',\n    )}`.execute(db)\n  }\n\n  override async releaseMigrationLock(): Promise<void> {\n    // Nothing to do here. `sp_getapplock` is automatically released at the\n    // end of the transaction and since `supportsTransactionalDdl` true, we know\n    // the `db` instance passed to acquireMigrationLock is actually a transaction.\n  }\n}\n"
  },
  {
    "path": "src/dialect/mssql/mssql-dialect-config.ts",
    "content": "import type { KyselyTypeError } from '../../util/type-error.js'\n\nexport interface MssqlDialectConfig {\n  /**\n   * When `true`, connections are reset to their initial states when released\n   * back to the pool, resulting in additional requests to the database.\n   *\n   * Defaults to `false`.\n   */\n  resetConnectionsOnRelease?: boolean\n\n  /**\n   * This dialect uses the `tarn` package to manage the connection pool to your\n   * database. To use it as a peer dependency and not bundle it with Kysely's code,\n   * you need to pass the `tarn` package itself. You also need to pass some pool options\n   * (excluding `create`, `destroy` and `validate` functions which are controlled by this dialect),\n   * `min` & `max` connections at the very least.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { MssqlDialect } from 'kysely'\n   * import * as Tarn from 'tarn'\n   * import * as Tedious from 'tedious'\n   *\n   * const dialect = new MssqlDialect({\n   *   tarn: { ...Tarn, options: { max: 10, min: 0 } },\n   *   tedious: {\n   *     ...Tedious,\n   *     connectionFactory: () => new Tedious.Connection({\n   *       // ...\n   *       server: 'localhost',\n   *       // ...\n   *     }),\n   *   }\n   * })\n   * ```\n   */\n  tarn: Tarn\n\n  /**\n   * This dialect uses the `tedious` package to communicate with your MS SQL Server\n   * database. To use it as a peer dependency and not bundle it with Kysely's code,\n   * you need to pass the `tedious` package itself. You also need to pass a factory\n   * function that creates new `tedious` `Connection` instances on demand.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { MssqlDialect } from 'kysely'\n   * import * as Tarn from 'tarn'\n   * import * as Tedious from 'tedious'\n   *\n   * const dialect = new MssqlDialect({\n   *   tarn: { ...Tarn, options: { max: 10, min: 0 } },\n   *   tedious: {\n   *     ...Tedious,\n   *     connectionFactory: () => new Tedious.Connection({\n   *       // ...\n   *       server: 'localhost',\n   *       // ...\n   *     }),\n   *   }\n   * })\n   * ```\n   */\n  tedious: Tedious\n\n  /**\n   * When `true`, connections are validated before being acquired from the pool,\n   * resulting in additional requests to the database.\n   *\n   * Defaults to `true`.\n   */\n  validateConnections?: boolean\n}\n\nexport interface Tedious {\n  connectionFactory: () => TediousConnection | Promise<TediousConnection>\n  ISOLATION_LEVEL: TediousIsolationLevel\n  Request: TediousRequestClass\n  // TODO: remove in v0.29.0\n  /**\n   * @deprecated use {@link MssqlDialectConfig.resetConnectionsOnRelease} instead.\n   */\n  resetConnectionOnRelease?: KyselyTypeError<'deprecated: use `MssqlDialectConfig.resetConnectionsOnRelease` instead'>\n  TYPES: TediousTypes\n}\n\nexport interface TediousConnection {\n  beginTransaction(\n    callback: (\n      err: Error | null | undefined,\n      transactionDescriptor?: any,\n    ) => void,\n    name?: string | undefined,\n    isolationLevel?: number | undefined,\n  ): void\n  cancel(): boolean\n  close(): void\n  commitTransaction(\n    callback: (err: Error | null | undefined) => void,\n    name?: string | undefined,\n  ): void\n  connect(connectListener: (err?: Error) => void): void\n  execSql(request: TediousRequest): void\n  off(event: 'error', listener: (error: unknown) => void): this\n  off(event: string, listener: (...args: any[]) => void): this\n  on(event: 'error', listener: (error: unknown) => void): this\n  on(event: string, listener: (...args: any[]) => void): this\n  once(event: 'end', listener: () => void): this\n  once(event: string, listener: (...args: any[]) => void): this\n  reset(callback: (err: Error | null | undefined) => void): void\n  rollbackTransaction(\n    callback: (err: Error | null | undefined) => void,\n    name?: string | undefined,\n  ): void\n  saveTransaction(\n    callback: (err: Error | null | undefined) => void,\n    name: string,\n  ): void\n}\n\nexport type TediousIsolationLevel = Record<string, number>\n\nexport interface TediousRequestClass {\n  new (\n    sqlTextOrProcedure: string | undefined,\n    callback: (error?: Error | null, rowCount?: number, rows?: any) => void,\n    options?: {\n      statementColumnEncryptionSetting?: any\n    },\n  ): TediousRequest\n}\n\nexport declare class TediousRequest {\n  addParameter(\n    name: string,\n    dataType: TediousDataType,\n    value?: unknown,\n    options?: Readonly<{\n      output?: boolean\n      length?: number\n      precision?: number\n      scale?: number\n    }> | null,\n  ): void\n  off(event: 'row', listener: (columns: any) => void): this\n  off(event: string, listener: (...args: any[]) => void): this\n  on(event: 'row', listener: (columns: any) => void): this\n  on(event: string, listener: (...args: any[]) => void): this\n  once(event: 'requestCompleted', listener: () => void): this\n  once(event: string, listener: (...args: any[]) => void): this\n  pause(): void\n  resume(): void\n}\n\nexport interface TediousTypes {\n  NVarChar: TediousDataType\n  BigInt: TediousDataType\n  Int: TediousDataType\n  Float: TediousDataType\n  Bit: TediousDataType\n  DateTime: TediousDataType\n  VarBinary: TediousDataType\n  [x: string]: TediousDataType\n}\n\nexport interface TediousDataType {}\n\nexport interface TediousColumnValue {\n  metadata: {\n    colName: string\n  }\n  value: any\n}\n\nexport interface Tarn {\n  /**\n   * Tarn.js' pool options, excluding `create`, `destroy` and `validate` functions,\n   * which must be implemented by this dialect.\n   */\n  options: Omit<TarnPoolOptions<any>, 'create' | 'destroy' | 'validate'> & {\n    // TODO: remove in v0.29.0\n    /**\n     * @deprecated use {@link MssqlDialectConfig.validateConnections} instead.\n     */\n    validateConnections?: KyselyTypeError<'deprecated: use `MssqlDialectConfig.validateConnections` instead'>\n  }\n\n  /**\n   * Tarn.js' Pool class.\n   */\n  Pool: typeof TarnPool\n}\n\nexport declare class TarnPool<R> {\n  constructor(opt: TarnPoolOptions<R>)\n  acquire(): TarnPendingRequest<R>\n  destroy(): any\n  release(resource: R): void\n}\n\nexport interface TarnPoolOptions<R> {\n  acquireTimeoutMillis?: number\n  create(cb: (err: Error | null, resource: R) => void): any | (() => Promise<R>)\n  createRetryIntervalMillis?: number\n  createTimeoutMillis?: number\n  destroy(resource: R): any\n  destroyTimeoutMillis?: number\n  idleTimeoutMillis?: number\n  log?(msg: string): any\n  max: number\n  min: number\n  propagateCreateError?: boolean\n  reapIntervalMillis?: number\n  validate?(resource: R): boolean\n}\n\nexport interface TarnPendingRequest<R> {\n  promise: Promise<R>\n  resolve: (resource: R) => void\n  reject: (err: Error) => void\n}\n"
  },
  {
    "path": "src/dialect/mssql/mssql-dialect.ts",
    "content": "import type { Driver } from '../../driver/driver.js'\nimport type { Kysely } from '../../kysely.js'\nimport type { QueryCompiler } from '../../query-compiler/query-compiler.js'\nimport type { DatabaseIntrospector } from '../database-introspector.js'\nimport type { DialectAdapter } from '../dialect-adapter.js'\nimport type { Dialect } from '../dialect.js'\nimport { MssqlAdapter } from './mssql-adapter.js'\nimport type { MssqlDialectConfig } from './mssql-dialect-config.js'\nimport { MssqlDriver } from './mssql-driver.js'\nimport { MssqlIntrospector } from './mssql-introspector.js'\nimport { MssqlQueryCompiler } from './mssql-query-compiler.js'\n\n/**\n * MS SQL Server dialect that uses the [tedious](https://tediousjs.github.io/tedious)\n * library.\n *\n * The constructor takes an instance of {@link MssqlDialectConfig}.\n *\n * ```ts\n * import * as Tedious from 'tedious'\n * import * as Tarn from 'tarn'\n *\n * const dialect = new MssqlDialect({\n *   tarn: {\n *     ...Tarn,\n *     options: {\n *       min: 0,\n *       max: 10,\n *     },\n *   },\n *   tedious: {\n *     ...Tedious,\n *     connectionFactory: () => new Tedious.Connection({\n *       authentication: {\n *         options: {\n *           password: 'password',\n *           userName: 'username',\n *         },\n *         type: 'default',\n *       },\n *       options: {\n *         database: 'some_db',\n *         port: 1433,\n *         trustServerCertificate: true,\n *       },\n *       server: 'localhost',\n *     }),\n *   },\n * })\n * ```\n */\nexport class MssqlDialect implements Dialect {\n  readonly #config: MssqlDialectConfig\n\n  constructor(config: MssqlDialectConfig) {\n    this.#config = config\n  }\n\n  createDriver(): Driver {\n    return new MssqlDriver(this.#config)\n  }\n\n  createQueryCompiler(): QueryCompiler {\n    return new MssqlQueryCompiler()\n  }\n\n  createAdapter(): DialectAdapter {\n    return new MssqlAdapter()\n  }\n\n  createIntrospector(db: Kysely<any>): DatabaseIntrospector {\n    return new MssqlIntrospector(db)\n  }\n}\n"
  },
  {
    "path": "src/dialect/mssql/mssql-driver.ts",
    "content": "import type {\n  DatabaseConnection,\n  QueryResult,\n} from '../../driver/database-connection.js'\nimport type {\n  Driver,\n  IsolationLevel,\n  TransactionSettings,\n} from '../../driver/driver.js'\nimport {\n  freeze,\n  isBigInt,\n  isBoolean,\n  isBuffer,\n  isDate,\n  isNull,\n  isNumber,\n  isString,\n  isUndefined,\n} from '../../util/object-utils.js'\nimport type {\n  MssqlDialectConfig,\n  TarnPool,\n  Tedious,\n  TediousColumnValue,\n  TediousConnection,\n  TediousRequest,\n} from './mssql-dialect-config.js'\nimport { CompiledQuery } from '../../query-compiler/compiled-query.js'\nimport { extendStackTrace } from '../../util/stack-trace-utils.js'\nimport { randomString } from '../../util/random-string.js'\nimport { Deferred } from '../../util/deferred.js'\n\nconst PRIVATE_RESET_METHOD: unique symbol = Symbol()\nconst PRIVATE_DESTROY_METHOD: unique symbol = Symbol()\nconst PRIVATE_VALIDATE_METHOD: unique symbol = Symbol()\n\nexport class MssqlDriver implements Driver {\n  readonly #config: MssqlDialectConfig\n  readonly #pool: TarnPool<MssqlConnection>\n\n  constructor(config: MssqlDialectConfig) {\n    this.#config = freeze({ ...config })\n\n    const { tarn, tedious, validateConnections } = this.#config\n    const {\n      validateConnections: deprecatedValidateConnections,\n      ...poolOptions\n    } = tarn.options\n\n    this.#pool = new tarn.Pool({\n      ...poolOptions,\n      create: async () => {\n        const connection = await tedious.connectionFactory()\n\n        return await new MssqlConnection(connection, tedious).connect()\n      },\n      destroy: async (connection) => {\n        await connection[PRIVATE_DESTROY_METHOD]()\n      },\n      // @ts-ignore `tarn` accepts a function that returns a promise here, but\n      // the types are not aligned and it type errors.\n      validate:\n        validateConnections === false ||\n        (deprecatedValidateConnections as any) === false\n          ? undefined\n          : (connection) => connection[PRIVATE_VALIDATE_METHOD](),\n    })\n  }\n\n  async init(): Promise<void> {\n    // noop\n  }\n\n  async acquireConnection(): Promise<DatabaseConnection> {\n    return await this.#pool.acquire().promise\n  }\n\n  async beginTransaction(\n    connection: MssqlConnection,\n    settings: TransactionSettings,\n  ): Promise<void> {\n    await connection.beginTransaction(settings)\n  }\n\n  async commitTransaction(connection: MssqlConnection): Promise<void> {\n    await connection.commitTransaction()\n  }\n\n  async rollbackTransaction(connection: MssqlConnection): Promise<void> {\n    await connection.rollbackTransaction()\n  }\n\n  async savepoint(\n    connection: MssqlConnection,\n    savepointName: string,\n  ): Promise<void> {\n    await connection.savepoint(savepointName)\n  }\n\n  async rollbackToSavepoint(\n    connection: MssqlConnection,\n    savepointName: string,\n  ): Promise<void> {\n    await connection.rollbackTransaction(savepointName)\n  }\n\n  async releaseConnection(connection: MssqlConnection): Promise<void> {\n    if (\n      this.#config.resetConnectionsOnRelease ||\n      this.#config.tedious.resetConnectionOnRelease\n    ) {\n      await connection[PRIVATE_RESET_METHOD]()\n    }\n\n    this.#pool.release(connection)\n  }\n\n  async destroy(): Promise<void> {\n    await this.#pool.destroy()\n  }\n}\n\nclass MssqlConnection implements DatabaseConnection {\n  readonly #connection: TediousConnection\n  #hasSocketError: boolean\n  readonly #tedious: Tedious\n\n  constructor(connection: TediousConnection, tedious: Tedious) {\n    this.#connection = connection\n    this.#hasSocketError = false\n    this.#tedious = tedious\n  }\n\n  async beginTransaction(settings: TransactionSettings): Promise<void> {\n    const { isolationLevel } = settings\n\n    await new Promise((resolve, reject) =>\n      this.#connection.beginTransaction(\n        (error) => {\n          if (error) reject(error)\n          else resolve(undefined)\n        },\n        isolationLevel ? randomString(8) : undefined,\n        isolationLevel\n          ? this.#getTediousIsolationLevel(isolationLevel)\n          : undefined,\n      ),\n    )\n  }\n\n  async commitTransaction(): Promise<void> {\n    await new Promise((resolve, reject) =>\n      this.#connection.commitTransaction((error) => {\n        if (error) reject(error)\n        else resolve(undefined)\n      }),\n    )\n  }\n\n  async connect(): Promise<this> {\n    const { promise: waitForConnected, reject, resolve } = new Deferred<void>()\n\n    this.#connection.connect((error) => {\n      if (error) {\n        return reject(error)\n      }\n\n      resolve()\n    })\n\n    this.#connection.on('error', (error) => {\n      if (\n        error instanceof Error &&\n        'code' in error &&\n        error.code === 'ESOCKET'\n      ) {\n        this.#hasSocketError = true\n      }\n\n      console.error(error)\n      reject(error)\n    })\n\n    function endListener() {\n      reject(\n        new Error(\n          'The connection ended without ever completing the connection',\n        ),\n      )\n    }\n\n    this.#connection.once('end', endListener)\n\n    await waitForConnected\n\n    this.#connection.off('end', endListener)\n\n    return this\n  }\n\n  async executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {\n    try {\n      const deferred = new Deferred<OnDone<O>>()\n\n      const request = new MssqlRequest<O>({\n        compiledQuery,\n        tedious: this.#tedious,\n        onDone: deferred,\n      })\n\n      this.#connection.execSql(request.request)\n\n      const { rowCount, rows } = await deferred.promise\n\n      return {\n        numAffectedRows: rowCount !== undefined ? BigInt(rowCount) : undefined,\n        rows,\n      }\n    } catch (err) {\n      throw extendStackTrace(err, new Error())\n    }\n  }\n\n  async rollbackTransaction(savepointName?: string): Promise<void> {\n    await new Promise((resolve, reject) =>\n      this.#connection.rollbackTransaction((error) => {\n        if (error) reject(error)\n        else resolve(undefined)\n      }, savepointName),\n    )\n  }\n\n  async savepoint(savepointName: string): Promise<void> {\n    await new Promise((resolve, reject) =>\n      this.#connection.saveTransaction((error) => {\n        if (error) reject(error)\n        else resolve(undefined)\n      }, savepointName),\n    )\n  }\n\n  async *streamQuery<O>(\n    compiledQuery: CompiledQuery,\n    chunkSize: number,\n  ): AsyncIterableIterator<QueryResult<O>> {\n    if (!Number.isInteger(chunkSize) || chunkSize <= 0) {\n      throw new Error('chunkSize must be a positive integer')\n    }\n\n    const request = new MssqlRequest<O>({\n      compiledQuery,\n      streamChunkSize: chunkSize,\n      tedious: this.#tedious,\n    })\n\n    this.#connection.execSql(request.request)\n\n    try {\n      while (true) {\n        const rows = await request.readChunk()\n\n        if (rows.length === 0) {\n          break\n        }\n\n        yield { rows }\n\n        if (rows.length < chunkSize) {\n          break\n        }\n      }\n    } finally {\n      await this.#cancelRequest(request)\n    }\n  }\n\n  #getTediousIsolationLevel(isolationLevel: IsolationLevel) {\n    const { ISOLATION_LEVEL } = this.#tedious\n\n    const mapper: Record<\n      IsolationLevel,\n      (typeof ISOLATION_LEVEL)[keyof typeof ISOLATION_LEVEL]\n    > = {\n      'read committed': ISOLATION_LEVEL.READ_COMMITTED,\n      'read uncommitted': ISOLATION_LEVEL.READ_UNCOMMITTED,\n      'repeatable read': ISOLATION_LEVEL.REPEATABLE_READ,\n      serializable: ISOLATION_LEVEL.SERIALIZABLE,\n      snapshot: ISOLATION_LEVEL.SNAPSHOT,\n    }\n\n    const tediousIsolationLevel = mapper[isolationLevel]\n\n    if (tediousIsolationLevel === undefined) {\n      throw new Error(`Unknown isolation level: ${isolationLevel}`)\n    }\n\n    return tediousIsolationLevel\n  }\n\n  #cancelRequest<O>(request: MssqlRequest<O>): Promise<void> {\n    return new Promise<void>((resolve) => {\n      request.request.once('requestCompleted', resolve)\n\n      const wasCanceled = this.#connection.cancel()\n\n      if (!wasCanceled) {\n        request.request.off('requestCompleted', resolve)\n        resolve()\n      }\n    })\n  }\n\n  [PRIVATE_DESTROY_METHOD](): Promise<void> {\n    if ('closed' in this.#connection && this.#connection.closed) {\n      return Promise.resolve()\n    }\n\n    return new Promise<void>((resolve) => {\n      this.#connection.once('end', resolve)\n\n      this.#connection.close()\n    })\n  }\n\n  async [PRIVATE_RESET_METHOD](): Promise<void> {\n    await new Promise<void>((resolve, reject) => {\n      this.#connection.reset((error) => {\n        if (error) {\n          return reject(error)\n        }\n\n        resolve()\n      })\n    })\n  }\n\n  async [PRIVATE_VALIDATE_METHOD](): Promise<boolean> {\n    if (this.#hasSocketError || this.#isConnectionClosed()) {\n      return false\n    }\n\n    try {\n      const deferred = new Deferred<OnDone<unknown>>()\n\n      const request = new MssqlRequest<unknown>({\n        compiledQuery: CompiledQuery.raw('select 1'),\n        onDone: deferred,\n        tedious: this.#tedious,\n      })\n\n      this.#connection.execSql(request.request)\n\n      await deferred.promise\n\n      return true\n    } catch {\n      return false\n    }\n  }\n\n  #isConnectionClosed(): boolean {\n    return 'closed' in this.#connection && Boolean(this.#connection.closed)\n  }\n}\n\ninterface OnDone<O> {\n  rowCount: number | undefined\n  rows: O[]\n}\n\ninterface PlainDeferred<O> {\n  reject: (reason: any) => void\n  resolve: (value?: O) => void\n}\n\nclass MssqlRequest<O> {\n  readonly #request: TediousRequest\n  readonly #rows: O[]\n  readonly #streamChunkSize: number | undefined\n  readonly #subscribers: Record<\n    string,\n    (event: 'completed' | 'chunkReady' | 'error', error?: unknown) => void\n  >\n  readonly #tedious: Tedious\n  #rowCount: number | undefined\n\n  constructor(props: MssqlRequestProps<O>) {\n    const { compiledQuery, onDone, streamChunkSize, tedious } = props\n\n    this.#rows = []\n    this.#streamChunkSize = streamChunkSize\n    this.#subscribers = {}\n    this.#tedious = tedious\n\n    if (onDone) {\n      const subscriptionKey = 'onDone'\n\n      this.#subscribers[subscriptionKey] = (event, error) => {\n        if (event === 'chunkReady') {\n          return\n        }\n\n        delete this.#subscribers[subscriptionKey]\n\n        if (event === 'error') {\n          return onDone.reject(error)\n        }\n\n        onDone.resolve({\n          rowCount: this.#rowCount,\n          rows: this.#rows,\n        })\n      }\n    }\n\n    this.#request = new this.#tedious.Request(\n      compiledQuery.sql,\n      (err, rowCount) => {\n        if (err) {\n          return Object.values(this.#subscribers).forEach((subscriber) =>\n            subscriber(\n              'error',\n              err instanceof AggregateError ? err.errors : err,\n            ),\n          )\n        }\n\n        this.#rowCount = rowCount\n      },\n    )\n\n    this.#addParametersToRequest(compiledQuery.parameters)\n    this.#attachListeners()\n  }\n\n  get request(): TediousRequest {\n    return this.#request\n  }\n\n  readChunk(): Promise<O[]> {\n    const subscriptionKey = this.readChunk.name\n\n    return new Promise<O[]>((resolve, reject) => {\n      this.#subscribers[subscriptionKey] = (event, error) => {\n        delete this.#subscribers[subscriptionKey]\n\n        if (event === 'error') {\n          return reject(error)\n        }\n\n        resolve(this.#rows.splice(0, this.#streamChunkSize))\n      }\n\n      this.#request.resume()\n    })\n  }\n\n  #addParametersToRequest(parameters: readonly unknown[]): void {\n    for (let i = 0; i < parameters.length; i++) {\n      const parameter = parameters[i]\n\n      this.#request.addParameter(\n        String(i + 1),\n        this.#getTediousDataType(parameter),\n        parameter,\n      )\n    }\n  }\n\n  #attachListeners(): void {\n    const pauseAndEmitChunkReady = this.#streamChunkSize\n      ? () => {\n          if (this.#streamChunkSize! <= this.#rows.length) {\n            this.#request.pause()\n\n            Object.values(this.#subscribers).forEach((subscriber) =>\n              subscriber('chunkReady'),\n            )\n          }\n        }\n      : () => {}\n\n    const rowListener = (columns: TediousColumnValue[]) => {\n      const row: Record<string, unknown> = {}\n\n      for (const column of columns) {\n        row[column.metadata.colName] = column.value\n      }\n\n      this.#rows.push(row as O)\n\n      pauseAndEmitChunkReady()\n    }\n\n    this.#request.on('row', rowListener)\n\n    this.#request.once('requestCompleted', () => {\n      Object.values(this.#subscribers).forEach((subscriber) =>\n        subscriber('completed'),\n      )\n      this.#request.off('row', rowListener)\n    })\n  }\n\n  #getTediousDataType(value: unknown): any {\n    if (isNull(value) || isUndefined(value) || isString(value)) {\n      return this.#tedious.TYPES.NVarChar\n    }\n\n    if (isBigInt(value) || (isNumber(value) && value % 1 === 0)) {\n      if (value < -2147483648 || value > 2147483647) {\n        return this.#tedious.TYPES.BigInt\n      } else {\n        return this.#tedious.TYPES.Int\n      }\n    }\n\n    if (isNumber(value)) {\n      return this.#tedious.TYPES.Float\n    }\n\n    if (isBoolean(value)) {\n      return this.#tedious.TYPES.Bit\n    }\n\n    if (isDate(value)) {\n      return this.#tedious.TYPES.DateTime\n    }\n\n    if (isBuffer(value)) {\n      return this.#tedious.TYPES.VarBinary\n    }\n\n    return this.#tedious.TYPES.NVarChar\n  }\n}\n\ninterface MssqlRequestProps<O> {\n  compiledQuery: CompiledQuery\n  onDone?: Deferred<OnDone<O>> | PlainDeferred<OnDone<O>>\n  streamChunkSize?: number\n  tedious: Tedious\n}\n"
  },
  {
    "path": "src/dialect/mssql/mssql-introspector.ts",
    "content": "import type { Kysely } from '../../kysely.js'\nimport type {\n  DatabaseIntrospector,\n  DatabaseMetadata,\n  DatabaseMetadataOptions,\n  SchemaMetadata,\n  TableMetadata,\n} from '../database-introspector.js'\nimport {\n  DEFAULT_MIGRATION_LOCK_TABLE,\n  DEFAULT_MIGRATION_TABLE,\n} from '../../migration/migrator.js'\nimport { freeze } from '../../util/object-utils.js'\n\nexport class MssqlIntrospector implements DatabaseIntrospector {\n  readonly #db: Kysely<MssqlSysTables>\n\n  constructor(db: Kysely<any>) {\n    this.#db = db\n  }\n\n  async getSchemas(): Promise<SchemaMetadata[]> {\n    return await this.#db.selectFrom('sys.schemas').select('name').execute()\n  }\n\n  async getTables(\n    options: DatabaseMetadataOptions = { withInternalKyselyTables: false },\n  ): Promise<TableMetadata[]> {\n    const rawColumns = await this.#db\n      .selectFrom('sys.tables as tables')\n      .leftJoin(\n        'sys.schemas as table_schemas',\n        'table_schemas.schema_id',\n        'tables.schema_id',\n      )\n      .innerJoin(\n        'sys.columns as columns',\n        'columns.object_id',\n        'tables.object_id',\n      )\n      .innerJoin(\n        'sys.types as types',\n        'types.user_type_id',\n        'columns.user_type_id',\n      )\n      .leftJoin(\n        'sys.schemas as type_schemas',\n        'type_schemas.schema_id',\n        'types.schema_id',\n      )\n      .leftJoin('sys.extended_properties as comments', (join) =>\n        join\n          .onRef('comments.major_id', '=', 'tables.object_id')\n          .onRef('comments.minor_id', '=', 'columns.column_id')\n          .on('comments.name', '=', 'MS_Description'),\n      )\n      .$if(!options.withInternalKyselyTables, (qb) =>\n        qb\n          .where('tables.name', '!=', DEFAULT_MIGRATION_TABLE)\n          .where('tables.name', '!=', DEFAULT_MIGRATION_LOCK_TABLE),\n      )\n      .select([\n        'tables.name as table_name',\n        (eb) =>\n          eb\n            .ref('tables.type')\n            .$castTo<\n              | MssqlSysTables['sys.tables']['type']\n              | MssqlSysTables['sys.views']['type']\n            >()\n            .as('table_type'),\n        'table_schemas.name as table_schema_name',\n        'columns.default_object_id as column_default_object_id',\n        'columns.generated_always_type_desc as column_generated_always_type',\n        'columns.is_computed as column_is_computed',\n        'columns.is_identity as column_is_identity',\n        'columns.is_nullable as column_is_nullable',\n        'columns.is_rowguidcol as column_is_rowguidcol',\n        'columns.name as column_name',\n        'types.is_nullable as type_is_nullable',\n        'types.name as type_name',\n        'type_schemas.name as type_schema_name',\n        'comments.value as column_comment',\n      ])\n      .unionAll(\n        this.#db\n          .selectFrom('sys.views as views')\n          .leftJoin(\n            'sys.schemas as view_schemas',\n            'view_schemas.schema_id',\n            'views.schema_id',\n          )\n          .innerJoin(\n            'sys.columns as columns',\n            'columns.object_id',\n            'views.object_id',\n          )\n          .innerJoin(\n            'sys.types as types',\n            'types.user_type_id',\n            'columns.user_type_id',\n          )\n          .leftJoin(\n            'sys.schemas as type_schemas',\n            'type_schemas.schema_id',\n            'types.schema_id',\n          )\n          .leftJoin('sys.extended_properties as comments', (join) =>\n            join\n              .onRef('comments.major_id', '=', 'views.object_id')\n              .onRef('comments.minor_id', '=', 'columns.column_id')\n              .on('comments.name', '=', 'MS_Description'),\n          )\n          .select([\n            'views.name as table_name',\n            'views.type as table_type',\n            'view_schemas.name as table_schema_name',\n            'columns.default_object_id as column_default_object_id',\n            'columns.generated_always_type_desc as column_generated_always_type',\n            'columns.is_computed as column_is_computed',\n            'columns.is_identity as column_is_identity',\n            'columns.is_nullable as column_is_nullable',\n            'columns.is_rowguidcol as column_is_rowguidcol',\n            'columns.name as column_name',\n            'types.is_nullable as type_is_nullable',\n            'types.name as type_name',\n            'type_schemas.name as type_schema_name',\n            'comments.value as column_comment',\n          ]),\n      )\n      .orderBy('table_schema_name')\n      .orderBy('table_name')\n      .orderBy('column_name')\n      .execute()\n\n    const tableDictionary: Record<string, TableMetadata> = {}\n\n    for (const rawColumn of rawColumns) {\n      const key = `${rawColumn.table_schema_name}.${rawColumn.table_name}`\n\n      const table = (tableDictionary[key] =\n        tableDictionary[key] ||\n        freeze({\n          columns: [],\n          isView: rawColumn.table_type === 'V ',\n          name: rawColumn.table_name,\n          schema: rawColumn.table_schema_name ?? undefined,\n        }))\n\n      table.columns.push(\n        freeze({\n          dataType: rawColumn.type_name,\n          dataTypeSchema: rawColumn.type_schema_name ?? undefined,\n          hasDefaultValue:\n            rawColumn.column_default_object_id > 0 ||\n            rawColumn.column_generated_always_type !== 'NOT_APPLICABLE' ||\n            rawColumn.column_is_identity ||\n            rawColumn.column_is_computed ||\n            rawColumn.column_is_rowguidcol,\n          isAutoIncrementing: rawColumn.column_is_identity,\n          isNullable:\n            rawColumn.column_is_nullable && rawColumn.type_is_nullable,\n          name: rawColumn.column_name,\n          comment: rawColumn.column_comment ?? undefined,\n        }),\n      )\n    }\n\n    return Object.values(tableDictionary)\n  }\n\n  async getMetadata(\n    options?: DatabaseMetadataOptions,\n  ): Promise<DatabaseMetadata> {\n    return {\n      tables: await this.getTables(options),\n    }\n  }\n}\n\ninterface MssqlSysTables {\n  'sys.columns': {\n    // collation_name: string | null\n    // column_encryption_key_database_name: null\n    // column_encryption_key_id: null\n    column_id: number\n    default_object_id: number\n    // encryption_algorithm_name: null\n    // encryption_type: null\n    // encryption_type_desc: null\n    // generated_always_type: number\n    generated_always_type_desc: string\n    // graph_type: number\n    // graph_type_desc: string\n    // is_ansi_padded: boolean\n    // is_column_set: boolean\n    is_computed: boolean\n    // is_data_deletion_filter_column: boolean\n    // is_dropped_ledger_column: boolean\n    // is_dts_replicated: boolean\n    // is_filestream: boolean\n    // is_hidden: boolean\n    is_identity: boolean\n    // is_masked: boolean\n    // is_merge_published: boolean\n    // is_non_sql_subscribed: boolean\n    is_nullable: boolean\n    // is_replicated: boolean\n    is_rowguidcol: boolean\n    // is_sparse: boolean\n    // is_xml_document: boolean\n    // ledger_view_column_type: null\n    // ledger_view_column_type_desc: null\n    // max_length: number\n    name: string\n    object_id: number\n    // precision: number\n    // rule_object_id: number\n    // scale: number\n    user_type_id: number\n    system_type_id: number\n  }\n  'sys.extended_properties': {\n    major_id: number\n    minor_id: number\n    name: string\n    value: string\n  }\n  'sys.schemas': {\n    name: string\n    // principal_id: number\n    schema_id: number\n  }\n  'sys.tables': {\n    // create_date: Date\n    // data_retention_period: number\n    // data_retention_period_unit: number\n    // data_retention_period_unit_desc: string\n    // durability: number\n    // durability_desc: string\n    // filestream_data_space_id: number | null\n    // has_replication_filter: boolean\n    // has_unchecked_assembly_data: boolean\n    // history_retention_period: null\n    // history_retention_period_unit: null\n    // history_retention_period_unit_desc: null\n    // history_table_id: null\n    // is_dropped_ledger_table: boolean\n    // is_edge: boolean\n    // is_external: boolean\n    // is_filetable: boolean\n    // is_memory_optimized: boolean\n    // is_merge_published: boolean\n    // is_ms_shipped: boolean\n    // is_node: boolean\n    // is_published: boolean\n    // is_remote_data_archive_enabled: boolean\n    // is_replicated: boolean\n    // is_schema_published: boolean\n    // is_sync_tran_subscribed: boolean\n    // is_tracked_by_cdc: boolean\n    // large_value_types_out_of_row: boolean\n    // ledger_type: number\n    // ledger_type_desc: string\n    // ledger_view_id: null\n    // lob_data_space_id: number\n    // lock_escalation: number\n    // lock_escalation_desc: string\n    // lock_on_bulk_load: boolean\n    // max_column_id_used: number\n    // modify_date: Date\n    name: string\n    object_id: number\n    // parent_object_id: number\n    // principal_id: number | null\n    schema_id: number\n    // temporal_type: number\n    // temporal_type_desc: string\n    // text_in_row_limit: number\n    type: 'U '\n    // type_desc: 'USER_TABLE'\n    // uses_ansi_nulls: boolean\n  }\n  'sys.types': {\n    // collation_name: string | null\n    // default_object_id: number\n    // is_assembly_type: boolean\n    is_nullable: boolean\n    // is_table_type: boolean\n    // is_user_defined: boolean\n    // max_length: number\n    name: string\n    // precision: number\n    // principal_id: number | null\n    // rule_object_id: number\n    // scale: number\n    schema_id: number\n    system_type_id: number\n    user_type_id: number\n  }\n  'sys.views': {\n    // create_date: Date\n    // has_opaque_metadata: boolean\n    // has_replication_filter: boolean\n    // has_snapshot: boolean\n    // has_unchecked_assembly_data: boolean\n    // is_date_correlation_view: boolean\n    // is_dropped_ledger_view: boolean\n    // is_msh_shipped: boolean\n    // is_published: boolean\n    // is_replicated: boolean\n    // is_schema_published: boolean\n    // is_tracked_by_cdc: boolean\n    // ledger_view_type: number\n    // ledger_view_type_desc: string\n    // modify_date: Date\n    name: string\n    object_id: number\n    // parent_object_id: number\n    // principal_id: number | null\n    schema_id: number\n    type: 'V '\n    // type_desc: 'VIEW'\n    // with_check_option: boolean\n  }\n}\n"
  },
  {
    "path": "src/dialect/mssql/mssql-query-compiler.ts",
    "content": "import type { AddColumnNode } from '../../operation-node/add-column-node.js'\nimport type { AlterTableColumnAlterationNode } from '../../operation-node/alter-table-node.js'\nimport type { DropColumnNode } from '../../operation-node/drop-column-node.js'\nimport type { OffsetNode } from '../../operation-node/offset-node.js'\nimport type { MergeQueryNode } from '../../operation-node/merge-query-node.js'\nimport { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js'\nimport type { CollateNode } from '../../operation-node/collate-node.js'\n\nconst COLLATION_CHAR_REGEX = /^[a-z0-9_]$/i\n\nexport class MssqlQueryCompiler extends DefaultQueryCompiler {\n  protected override getCurrentParameterPlaceholder(): string {\n    return `@${this.numParameters}`\n  }\n\n  protected override visitOffset(node: OffsetNode): void {\n    super.visitOffset(node)\n    this.append(' rows')\n  }\n\n  // mssql allows multi-column alterations in a single statement,\n  // but you can only use the command keyword/s once.\n  // it also doesn't support multiple kinds of commands in the same\n  // alter table statement, but we compile that anyway for the sake\n  // of WYSIWYG.\n  protected override compileColumnAlterations(\n    columnAlterations: readonly AlterTableColumnAlterationNode[],\n  ): void {\n    const nodesByKind: Partial<\n      Record<\n        AlterTableColumnAlterationNode['kind'],\n        AlterTableColumnAlterationNode[]\n      >\n    > = {}\n\n    for (const columnAlteration of columnAlterations) {\n      if (!nodesByKind[columnAlteration.kind]) {\n        nodesByKind[columnAlteration.kind] = []\n      }\n\n      nodesByKind[columnAlteration.kind]!.push(columnAlteration)\n    }\n\n    let first = true\n\n    if (nodesByKind.AddColumnNode) {\n      this.append('add ')\n      this.compileList(nodesByKind.AddColumnNode)\n      first = false\n    }\n\n    // multiple of these are not really supported by mssql,\n    // but for the sake of WYSIWYG.\n    if (nodesByKind.AlterColumnNode) {\n      if (!first) this.append(', ')\n      this.compileList(nodesByKind.AlterColumnNode)\n    }\n\n    if (nodesByKind.DropColumnNode) {\n      if (!first) this.append(', ')\n      this.append('drop column ')\n      this.compileList(nodesByKind.DropColumnNode)\n    }\n\n    // not really supported by mssql, but for the sake of WYSIWYG.\n    if (nodesByKind.ModifyColumnNode) {\n      if (!first) this.append(', ')\n      this.compileList(nodesByKind.ModifyColumnNode)\n    }\n\n    // not really supported by mssql, but for the sake of WYSIWYG.\n    if (nodesByKind.RenameColumnNode) {\n      if (!first) this.append(', ')\n      this.compileList(nodesByKind.RenameColumnNode)\n    }\n  }\n\n  protected override visitAddColumn(node: AddColumnNode): void {\n    this.visitNode(node.column)\n  }\n\n  protected override visitDropColumn(node: DropColumnNode): void {\n    this.visitNode(node.column)\n  }\n\n  protected override visitMergeQuery(node: MergeQueryNode): void {\n    super.visitMergeQuery(node)\n    this.append(';')\n  }\n\n  protected override visitCollate(node: CollateNode): void {\n    this.append('collate ')\n\n    const { name } = node.collation\n\n    for (const char of name) {\n      if (!COLLATION_CHAR_REGEX.test(char)) {\n        throw new Error(`Invalid collation: ${name}`)\n      }\n    }\n\n    this.append(name)\n  }\n\n  protected override announcesNewColumnDataType(): boolean {\n    return false\n  }\n}\n"
  },
  {
    "path": "src/dialect/mysql/mysql-adapter.ts",
    "content": "import type { Kysely } from '../../kysely.js'\nimport { sql } from '../../raw-builder/sql.js'\nimport { DialectAdapterBase } from '../dialect-adapter-base.js'\nimport type { MigrationLockOptions } from '../dialect-adapter.js'\n\nconst LOCK_ID = 'ea586330-2c93-47c8-908d-981d9d270f9d'\nconst LOCK_TIMEOUT_SECONDS = 60 * 60\n\nexport class MysqlAdapter extends DialectAdapterBase {\n  override get supportsTransactionalDdl(): boolean {\n    return false\n  }\n\n  override get supportsReturning(): boolean {\n    return false\n  }\n\n  override async acquireMigrationLock(\n    db: Kysely<any>,\n    _opt: MigrationLockOptions,\n  ): Promise<void> {\n    // Kysely uses a single connection to run the migrations. Because of that, we\n    // can take a lock using `get_lock`. Locks acquired using `get_lock` get\n    // released when the connection is destroyed (session ends) or when the lock\n    // is released using `release_lock`. This way we know that the lock is either\n    // released by us after successfull or failed migrations OR it's released by\n    // MySQL if the process gets killed for some reason.\n    await sql`select get_lock(${sql.lit(LOCK_ID)}, ${sql.lit(\n      LOCK_TIMEOUT_SECONDS,\n    )})`.execute(db)\n  }\n\n  override async releaseMigrationLock(\n    db: Kysely<any>,\n    _opt: MigrationLockOptions,\n  ): Promise<void> {\n    await sql`select release_lock(${sql.lit(LOCK_ID)})`.execute(db)\n  }\n}\n"
  },
  {
    "path": "src/dialect/mysql/mysql-dialect-config.ts",
    "content": "import type { DatabaseConnection } from '../../driver/database-connection.js'\n\n/**\n * Config for the MySQL dialect.\n *\n * https://github.com/sidorares/node-mysql2#using-connection-pools\n */\nexport interface MysqlDialectConfig {\n  /**\n   * A mysql2 Pool instance or a function that returns one.\n   *\n   * If a function is provided, it's called once when the first query is executed.\n   *\n   * https://github.com/sidorares/node-mysql2#using-connection-pools\n   */\n  pool: MysqlPool | (() => Promise<MysqlPool>)\n\n  /**\n   * Called once for each created connection.\n   */\n  onCreateConnection?: (connection: DatabaseConnection) => Promise<void>\n\n  /**\n   * Called every time a connection is acquired from the connection pool.\n   */\n  onReserveConnection?: (connection: DatabaseConnection) => Promise<void>\n}\n\n/**\n * This interface is the subset of mysql2 driver's `Pool` class that\n * kysely needs.\n *\n * We don't use the type from `mysql2` here to not have a dependency to it.\n *\n * https://github.com/sidorares/node-mysql2#using-connection-pools\n */\nexport interface MysqlPool {\n  getConnection(\n    callback: (error: unknown, connection: MysqlPoolConnection) => void,\n  ): void\n  end(callback: (error: unknown) => void): void\n}\n\nexport interface MysqlPoolConnection {\n  query(\n    sql: string,\n    parameters: Array<unknown>,\n  ): { stream: <T>(options: MysqlStreamOptions) => MysqlStream<T> }\n  query(\n    sql: string,\n    parameters: Array<unknown>,\n    callback: (error: unknown, result: MysqlQueryResult) => void,\n  ): void\n  release(): void\n}\n\nexport interface MysqlStreamOptions {\n  highWaterMark?: number\n  objectMode?: true\n}\n\nexport interface MysqlStream<T> {\n  [Symbol.asyncIterator](): AsyncIterableIterator<T>\n}\n\nexport interface MysqlOkPacket {\n  affectedRows: number\n  changedRows: number\n  insertId: number\n}\n\nexport type MysqlQueryResult = MysqlOkPacket | Record<string, unknown>[]\n"
  },
  {
    "path": "src/dialect/mysql/mysql-dialect.ts",
    "content": "import type { Driver } from '../../driver/driver.js'\nimport type { Kysely } from '../../kysely.js'\nimport type { QueryCompiler } from '../../query-compiler/query-compiler.js'\nimport type { Dialect } from '../dialect.js'\nimport type { DatabaseIntrospector } from '../database-introspector.js'\nimport { MysqlDriver } from './mysql-driver.js'\nimport { MysqlQueryCompiler } from './mysql-query-compiler.js'\nimport { MysqlIntrospector } from './mysql-introspector.js'\nimport type { DialectAdapter } from '../dialect-adapter.js'\nimport { MysqlAdapter } from './mysql-adapter.js'\nimport type { MysqlDialectConfig } from './mysql-dialect-config.js'\n\n/**\n * MySQL dialect that uses the [mysql2](https://github.com/sidorares/node-mysql2#readme) library.\n *\n * The constructor takes an instance of {@link MysqlDialectConfig}.\n *\n * ```ts\n * import { createPool } from 'mysql2'\n *\n * new MysqlDialect({\n *   pool: createPool({\n *     database: 'some_db',\n *     host: 'localhost',\n *   })\n * })\n * ```\n *\n * If you want the pool to only be created once it's first used, `pool`\n * can be a function:\n *\n * ```ts\n * import { createPool } from 'mysql2'\n *\n * new MysqlDialect({\n *   pool: async () => createPool({\n *     database: 'some_db',\n *     host: 'localhost',\n *   })\n * })\n * ```\n */\nexport class MysqlDialect implements Dialect {\n  readonly #config: MysqlDialectConfig\n\n  constructor(config: MysqlDialectConfig) {\n    this.#config = config\n  }\n\n  createDriver(): Driver {\n    return new MysqlDriver(this.#config)\n  }\n\n  createQueryCompiler(): QueryCompiler {\n    return new MysqlQueryCompiler()\n  }\n\n  createAdapter(): DialectAdapter {\n    return new MysqlAdapter()\n  }\n\n  createIntrospector(db: Kysely<any>): DatabaseIntrospector {\n    return new MysqlIntrospector(db)\n  }\n}\n"
  },
  {
    "path": "src/dialect/mysql/mysql-driver.ts",
    "content": "import type {\n  DatabaseConnection,\n  QueryResult,\n} from '../../driver/database-connection.js'\nimport type { Driver, TransactionSettings } from '../../driver/driver.js'\nimport { parseSavepointCommand } from '../../parser/savepoint-parser.js'\nimport { CompiledQuery } from '../../query-compiler/compiled-query.js'\nimport type { QueryCompiler } from '../../query-compiler/query-compiler.js'\nimport { isFunction, isObject, freeze } from '../../util/object-utils.js'\nimport { createQueryId } from '../../util/query-id.js'\nimport { extendStackTrace } from '../../util/stack-trace-utils.js'\nimport type {\n  MysqlDialectConfig,\n  MysqlOkPacket,\n  MysqlPool,\n  MysqlPoolConnection,\n  MysqlQueryResult,\n} from './mysql-dialect-config.js'\n\nconst PRIVATE_RELEASE_METHOD: unique symbol = Symbol()\n\nexport class MysqlDriver implements Driver {\n  readonly #config: MysqlDialectConfig\n  readonly #connections = new WeakMap<MysqlPoolConnection, DatabaseConnection>()\n  #pool?: MysqlPool\n\n  constructor(configOrPool: MysqlDialectConfig) {\n    this.#config = freeze({ ...configOrPool })\n  }\n\n  async init(): Promise<void> {\n    this.#pool = isFunction(this.#config.pool)\n      ? await this.#config.pool()\n      : this.#config.pool\n  }\n\n  async acquireConnection(): Promise<DatabaseConnection> {\n    const rawConnection = await this.#acquireConnection()\n    let connection = this.#connections.get(rawConnection)\n\n    if (!connection) {\n      connection = new MysqlConnection(rawConnection)\n      this.#connections.set(rawConnection, connection)\n\n      // The driver must take care of calling `onCreateConnection` when a new\n      // connection is created. The `mysql2` module doesn't provide an async hook\n      // for the connection creation. We need to call the method explicitly.\n      if (this.#config?.onCreateConnection) {\n        await this.#config.onCreateConnection(connection)\n      }\n    }\n\n    if (this.#config?.onReserveConnection) {\n      await this.#config.onReserveConnection(connection)\n    }\n\n    return connection\n  }\n\n  async #acquireConnection(): Promise<MysqlPoolConnection> {\n    return new Promise((resolve, reject) => {\n      this.#pool!.getConnection(async (err, rawConnection) => {\n        if (err) {\n          reject(err)\n        } else {\n          resolve(rawConnection)\n        }\n      })\n    })\n  }\n\n  async beginTransaction(\n    connection: DatabaseConnection,\n    settings: TransactionSettings,\n  ): Promise<void> {\n    if (settings.isolationLevel || settings.accessMode) {\n      const parts: string[] = []\n\n      if (settings.isolationLevel) {\n        parts.push(`isolation level ${settings.isolationLevel}`)\n      }\n\n      if (settings.accessMode) {\n        parts.push(settings.accessMode)\n      }\n\n      const sql = `set transaction ${parts.join(', ')}`\n\n      // On MySQL this sets the isolation level of the next transaction.\n      await connection.executeQuery(CompiledQuery.raw(sql))\n    }\n\n    await connection.executeQuery(CompiledQuery.raw('begin'))\n  }\n\n  async commitTransaction(connection: DatabaseConnection): Promise<void> {\n    await connection.executeQuery(CompiledQuery.raw('commit'))\n  }\n\n  async rollbackTransaction(connection: DatabaseConnection): Promise<void> {\n    await connection.executeQuery(CompiledQuery.raw('rollback'))\n  }\n\n  async savepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    await connection.executeQuery(\n      compileQuery(\n        parseSavepointCommand('savepoint', savepointName),\n        createQueryId(),\n      ),\n    )\n  }\n\n  async rollbackToSavepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    await connection.executeQuery(\n      compileQuery(\n        parseSavepointCommand('rollback to', savepointName),\n        createQueryId(),\n      ),\n    )\n  }\n\n  async releaseSavepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    await connection.executeQuery(\n      compileQuery(\n        parseSavepointCommand('release savepoint', savepointName),\n        createQueryId(),\n      ),\n    )\n  }\n\n  async releaseConnection(connection: MysqlConnection): Promise<void> {\n    connection[PRIVATE_RELEASE_METHOD]()\n  }\n\n  async destroy(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      this.#pool!.end((err) => {\n        if (err) {\n          reject(err)\n        } else {\n          resolve()\n        }\n      })\n    })\n  }\n}\n\nfunction isOkPacket(obj: unknown): obj is MysqlOkPacket {\n  return isObject(obj) && 'insertId' in obj && 'affectedRows' in obj\n}\n\nclass MysqlConnection implements DatabaseConnection {\n  readonly #rawConnection: MysqlPoolConnection\n\n  constructor(rawConnection: MysqlPoolConnection) {\n    this.#rawConnection = rawConnection\n  }\n\n  async executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {\n    try {\n      const result = await this.#executeQuery(compiledQuery)\n\n      if (isOkPacket(result)) {\n        const { insertId, affectedRows, changedRows } = result\n\n        return {\n          insertId:\n            insertId !== undefined &&\n            insertId !== null &&\n            insertId.toString() !== '0'\n              ? BigInt(insertId)\n              : undefined,\n          numAffectedRows:\n            affectedRows !== undefined && affectedRows !== null\n              ? BigInt(affectedRows)\n              : undefined,\n          numChangedRows:\n            changedRows !== undefined && changedRows !== null\n              ? BigInt(changedRows)\n              : undefined,\n          rows: [],\n        }\n      } else if (Array.isArray(result)) {\n        return {\n          rows: result as O[],\n        }\n      }\n\n      return {\n        rows: [],\n      }\n    } catch (err) {\n      throw extendStackTrace(err, new Error())\n    }\n  }\n\n  #executeQuery(compiledQuery: CompiledQuery): Promise<MysqlQueryResult> {\n    return new Promise((resolve, reject) => {\n      this.#rawConnection.query(\n        compiledQuery.sql,\n        compiledQuery.parameters as Array<unknown>,\n        (err, result) => {\n          if (err) {\n            reject(err)\n          } else {\n            resolve(result)\n          }\n        },\n      )\n    })\n  }\n\n  async *streamQuery<O>(\n    compiledQuery: CompiledQuery,\n    _chunkSize: number,\n  ): AsyncIterableIterator<QueryResult<O>> {\n    const stream = this.#rawConnection\n      .query(compiledQuery.sql, compiledQuery.parameters as Array<unknown>)\n      .stream<O>({\n        objectMode: true,\n      })\n\n    try {\n      for await (const row of stream) {\n        yield {\n          rows: [row],\n        }\n      }\n    } catch (ex) {\n      if (\n        ex &&\n        typeof ex === 'object' &&\n        'code' in ex &&\n        // @ts-ignore\n        ex.code === 'ERR_STREAM_PREMATURE_CLOSE'\n      ) {\n        // Most likely because of https://github.com/mysqljs/mysql/blob/master/lib/protocol/sequences/Query.js#L220\n        return\n      }\n\n      throw ex\n    }\n  }\n\n  [PRIVATE_RELEASE_METHOD](): void {\n    this.#rawConnection.release()\n  }\n}\n"
  },
  {
    "path": "src/dialect/mysql/mysql-introspector.ts",
    "content": "import type {\n  DatabaseIntrospector,\n  DatabaseMetadata,\n  DatabaseMetadataOptions,\n  SchemaMetadata,\n  TableMetadata,\n} from '../database-introspector.js'\nimport {\n  DEFAULT_MIGRATION_LOCK_TABLE,\n  DEFAULT_MIGRATION_TABLE,\n} from '../../migration/migrator.js'\nimport type { Kysely } from '../../kysely.js'\nimport { freeze } from '../../util/object-utils.js'\nimport { sql } from '../../raw-builder/sql.js'\n\nexport class MysqlIntrospector implements DatabaseIntrospector {\n  readonly #db: Kysely<any>\n\n  constructor(db: Kysely<any>) {\n    this.#db = db\n  }\n\n  async getSchemas(): Promise<SchemaMetadata[]> {\n    let rawSchemas = await this.#db\n      .selectFrom('information_schema.schemata')\n      .select('schema_name')\n      .$castTo<RawSchemaMetadata>()\n      .execute()\n\n    return rawSchemas.map((it) => ({ name: it.SCHEMA_NAME }))\n  }\n\n  async getTables(\n    options: DatabaseMetadataOptions = { withInternalKyselyTables: false },\n  ): Promise<TableMetadata[]> {\n    let query = this.#db\n      .selectFrom('information_schema.columns as columns')\n      .innerJoin('information_schema.tables as tables', (b) =>\n        b\n          .onRef('columns.TABLE_CATALOG', '=', 'tables.TABLE_CATALOG')\n          .onRef('columns.TABLE_SCHEMA', '=', 'tables.TABLE_SCHEMA')\n          .onRef('columns.TABLE_NAME', '=', 'tables.TABLE_NAME'),\n      )\n      .select([\n        'columns.COLUMN_NAME',\n        'columns.COLUMN_DEFAULT',\n        'columns.TABLE_NAME',\n        'columns.TABLE_SCHEMA',\n        'tables.TABLE_TYPE',\n        'columns.IS_NULLABLE',\n        'columns.DATA_TYPE',\n        'columns.EXTRA',\n        'columns.COLUMN_COMMENT',\n      ])\n      .where('columns.TABLE_SCHEMA', '=', sql`database()`)\n      .orderBy('columns.TABLE_NAME')\n      .orderBy('columns.ORDINAL_POSITION')\n      .$castTo<RawColumnMetadata>()\n\n    if (!options.withInternalKyselyTables) {\n      query = query\n        .where('columns.TABLE_NAME', '!=', DEFAULT_MIGRATION_TABLE)\n        .where('columns.TABLE_NAME', '!=', DEFAULT_MIGRATION_LOCK_TABLE)\n    }\n\n    const rawColumns = await query.execute()\n    return this.#parseTableMetadata(rawColumns)\n  }\n\n  async getMetadata(\n    options?: DatabaseMetadataOptions,\n  ): Promise<DatabaseMetadata> {\n    return {\n      tables: await this.getTables(options),\n    }\n  }\n\n  #parseTableMetadata(columns: RawColumnMetadata[]): TableMetadata[] {\n    return columns.reduce<TableMetadata[]>((tables, it) => {\n      let table = tables.find((tbl) => tbl.name === it.TABLE_NAME)\n\n      if (!table) {\n        table = freeze({\n          name: it.TABLE_NAME,\n          isView: it.TABLE_TYPE === 'VIEW',\n          schema: it.TABLE_SCHEMA,\n          columns: [],\n        })\n\n        tables.push(table)\n      }\n\n      table.columns.push(\n        freeze({\n          name: it.COLUMN_NAME,\n          dataType: it.DATA_TYPE,\n          isNullable: it.IS_NULLABLE === 'YES',\n          isAutoIncrementing: it.EXTRA.toLowerCase().includes('auto_increment'),\n          hasDefaultValue: it.COLUMN_DEFAULT !== null,\n          comment: it.COLUMN_COMMENT === '' ? undefined : it.COLUMN_COMMENT,\n        }),\n      )\n\n      return tables\n    }, [])\n  }\n}\n\ninterface RawSchemaMetadata {\n  SCHEMA_NAME: string\n}\n\ninterface RawColumnMetadata {\n  COLUMN_NAME: string\n  COLUMN_DEFAULT: any\n  TABLE_NAME: string\n  TABLE_SCHEMA: string\n  TABLE_TYPE: string\n  IS_NULLABLE: 'YES' | 'NO'\n  DATA_TYPE: string\n  EXTRA: string\n  COLUMN_COMMENT: string\n}\n"
  },
  {
    "path": "src/dialect/mysql/mysql-query-compiler.ts",
    "content": "import type { CreateIndexNode } from '../../operation-node/create-index-node.js'\nimport { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js'\n\nconst LITERAL_ESCAPE_REGEX = /\\\\|'/g\nconst ID_WRAP_REGEX = /`/g\n\nexport class MysqlQueryCompiler extends DefaultQueryCompiler {\n  protected override getCurrentParameterPlaceholder(): string {\n    return '?'\n  }\n\n  protected override getLeftExplainOptionsWrapper(): string {\n    return ''\n  }\n\n  protected override getExplainOptionAssignment(): string {\n    return '='\n  }\n\n  protected override getExplainOptionsDelimiter(): string {\n    return ' '\n  }\n\n  protected override getRightExplainOptionsWrapper(): string {\n    return ''\n  }\n\n  protected override getLeftIdentifierWrapper(): string {\n    return ID_WRAP_REGEX.source\n  }\n\n  protected override getRightIdentifierWrapper(): string {\n    return ID_WRAP_REGEX.source\n  }\n\n  protected override sanitizeIdentifier(identifier: string): string {\n    return identifier.replace(ID_WRAP_REGEX, '``')\n  }\n\n  /**\n   * MySQL requires escaping backslashes in string literals when using the\n   * default NO_BACKSLASH_ESCAPES=OFF mode. Without this, a backslash\n   * followed by a quote (\\') can break out of the string literal.\n   *\n   * @see https://dev.mysql.com/doc/refman/9.6/en/string-literals.html\n   */\n  protected override sanitizeStringLiteral(value: string): string {\n    return value.replace(LITERAL_ESCAPE_REGEX, (char) =>\n      char === '\\\\' ? '\\\\\\\\' : \"''\",\n    )\n  }\n\n  protected override visitCreateIndex(node: CreateIndexNode): void {\n    this.append('create ')\n\n    if (node.unique) {\n      this.append('unique ')\n    }\n\n    this.append('index ')\n\n    if (node.ifNotExists) {\n      this.append('if not exists ')\n    }\n\n    this.visitNode(node.name)\n\n    if (node.using) {\n      this.append(' using ')\n      this.visitNode(node.using)\n    }\n\n    if (node.table) {\n      this.append(' on ')\n      this.visitNode(node.table)\n    }\n\n    if (node.columns) {\n      this.append(' (')\n      this.compileList(node.columns)\n      this.append(')')\n    }\n\n    if (node.where) {\n      this.append(' ')\n      this.visitNode(node.where)\n    }\n  }\n}\n"
  },
  {
    "path": "src/dialect/postgres/postgres-adapter.ts",
    "content": "import type { Kysely } from '../../kysely.js'\nimport { sql } from '../../raw-builder/sql.js'\nimport { DialectAdapterBase } from '../dialect-adapter-base.js'\nimport type { MigrationLockOptions } from '../dialect-adapter.js'\n\n// Random id for our transaction lock.\nconst LOCK_ID = BigInt('3853314791062309107')\n\nexport class PostgresAdapter extends DialectAdapterBase {\n  override get supportsTransactionalDdl(): boolean {\n    return true\n  }\n\n  override get supportsReturning(): boolean {\n    return true\n  }\n\n  override async acquireMigrationLock(\n    db: Kysely<any>,\n    _opt: MigrationLockOptions,\n  ): Promise<void> {\n    // Acquire a transaction level advisory lock.\n    await sql`select pg_advisory_xact_lock(${sql.lit(LOCK_ID)})`.execute(db)\n  }\n\n  override async releaseMigrationLock(\n    _db: Kysely<any>,\n    _opt: MigrationLockOptions,\n  ): Promise<void> {\n    // Nothing to do here. `pg_advisory_xact_lock` is automatically released at the\n    // end of the transaction and since `supportsTransactionalDdl` true, we know\n    // the `db` instance passed to acquireMigrationLock is actually a transaction.\n  }\n}\n"
  },
  {
    "path": "src/dialect/postgres/postgres-dialect-config.ts",
    "content": "import type { DatabaseConnection } from '../../driver/database-connection.js'\n\n/**\n * Config for the PostgreSQL dialect.\n */\nexport interface PostgresDialectConfig {\n  /**\n   * A postgres Pool instance or a function that returns one.\n   *\n   * If a function is provided, it's called once when the first query is executed.\n   *\n   * https://node-postgres.com/apis/pool\n   */\n  pool: PostgresPool | (() => Promise<PostgresPool>)\n\n  /**\n   * https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor\n   *\n   * ```ts\n   * import { PostgresDialect } from 'kysely'\n   * import { Pool } from 'pg'\n   * import Cursor from 'pg-cursor'\n   * // or import * as Cursor from 'pg-cursor'\n   *\n   * new PostgresDialect({\n   *  cursor: Cursor,\n   *  pool: new Pool('postgres://localhost:5432/mydb')\n   * })\n   * ```\n   */\n  cursor?: PostgresCursorConstructor\n\n  /**\n   * Called once for each created connection.\n   */\n  onCreateConnection?: (connection: DatabaseConnection) => Promise<void>\n\n  /**\n   * Called every time a connection is acquired from the pool.\n   */\n  onReserveConnection?: (connection: DatabaseConnection) => Promise<void>\n}\n\n/**\n * This interface is the subset of pg driver's `Pool` class that\n * kysely needs.\n *\n * We don't use the type from `pg` here to not have a dependency to it.\n *\n * https://node-postgres.com/apis/pool\n */\nexport interface PostgresPool {\n  connect(): Promise<PostgresPoolClient>\n  end(): Promise<void>\n}\n\nexport interface PostgresPoolClient {\n  query<R>(\n    sql: string,\n    parameters: ReadonlyArray<unknown>,\n  ): Promise<PostgresQueryResult<R>>\n  query<R>(cursor: PostgresCursor<R>): PostgresCursor<R>\n  release(): void\n}\n\nexport interface PostgresCursor<T> {\n  read(rowsCount: number): Promise<T[]>\n  close(): Promise<void>\n}\n\nexport type PostgresCursorConstructor = new <T>(\n  sql: string,\n  parameters: unknown[],\n) => PostgresCursor<T>\n\nexport interface PostgresQueryResult<R> {\n  command: 'UPDATE' | 'DELETE' | 'INSERT' | 'SELECT' | 'MERGE'\n  rowCount: number\n  rows: R[]\n}\n\nexport interface PostgresStream<T> {\n  [Symbol.asyncIterator](): AsyncIterableIterator<T>\n}\n"
  },
  {
    "path": "src/dialect/postgres/postgres-dialect.ts",
    "content": "import type { Driver } from '../../driver/driver.js'\nimport type { Kysely } from '../../kysely.js'\nimport type { QueryCompiler } from '../../query-compiler/query-compiler.js'\nimport type { Dialect } from '../dialect.js'\nimport { PostgresDriver } from './postgres-driver.js'\nimport type { DatabaseIntrospector } from '../database-introspector.js'\nimport { PostgresIntrospector } from './postgres-introspector.js'\nimport { PostgresQueryCompiler } from './postgres-query-compiler.js'\nimport type { DialectAdapter } from '../dialect-adapter.js'\nimport { PostgresAdapter } from './postgres-adapter.js'\nimport type { PostgresDialectConfig } from './postgres-dialect-config.js'\n\n/**\n * PostgreSQL dialect that uses the [pg](https://node-postgres.com/) library.\n *\n * The constructor takes an instance of {@link PostgresDialectConfig}.\n *\n * ```ts\n * import { Pool } from 'pg'\n *\n * new PostgresDialect({\n *   pool: new Pool({\n *     database: 'some_db',\n *     host: 'localhost',\n *   })\n * })\n * ```\n *\n * If you want the pool to only be created once it's first used, `pool`\n * can be a function:\n *\n * ```ts\n * import { Pool } from 'pg'\n *\n * new PostgresDialect({\n *   pool: async () => new Pool({\n *     database: 'some_db',\n *     host: 'localhost',\n *   })\n * })\n * ```\n */\nexport class PostgresDialect implements Dialect {\n  readonly #config: PostgresDialectConfig\n\n  constructor(config: PostgresDialectConfig) {\n    this.#config = config\n  }\n\n  createDriver(): Driver {\n    return new PostgresDriver(this.#config)\n  }\n\n  createQueryCompiler(): QueryCompiler {\n    return new PostgresQueryCompiler()\n  }\n\n  createAdapter(): DialectAdapter {\n    return new PostgresAdapter()\n  }\n\n  createIntrospector(db: Kysely<any>): DatabaseIntrospector {\n    return new PostgresIntrospector(db)\n  }\n}\n"
  },
  {
    "path": "src/dialect/postgres/postgres-driver.ts",
    "content": "import type {\n  DatabaseConnection,\n  QueryResult,\n} from '../../driver/database-connection.js'\nimport type { Driver, TransactionSettings } from '../../driver/driver.js'\nimport { parseSavepointCommand } from '../../parser/savepoint-parser.js'\nimport { CompiledQuery } from '../../query-compiler/compiled-query.js'\nimport type { QueryCompiler } from '../../query-compiler/query-compiler.js'\nimport { isFunction, freeze } from '../../util/object-utils.js'\nimport { createQueryId } from '../../util/query-id.js'\nimport { extendStackTrace } from '../../util/stack-trace-utils.js'\nimport type {\n  PostgresCursorConstructor,\n  PostgresDialectConfig,\n  PostgresPool,\n  PostgresPoolClient,\n} from './postgres-dialect-config.js'\n\nconst PRIVATE_RELEASE_METHOD: unique symbol = Symbol()\n\nexport class PostgresDriver implements Driver {\n  readonly #config: PostgresDialectConfig\n  readonly #connections = new WeakMap<PostgresPoolClient, DatabaseConnection>()\n  #pool?: PostgresPool\n\n  constructor(config: PostgresDialectConfig) {\n    this.#config = freeze({ ...config })\n  }\n\n  async init(): Promise<void> {\n    this.#pool = isFunction(this.#config.pool)\n      ? await this.#config.pool()\n      : this.#config.pool\n  }\n\n  async acquireConnection(): Promise<DatabaseConnection> {\n    const client = await this.#pool!.connect()\n    let connection = this.#connections.get(client)\n\n    if (!connection) {\n      connection = new PostgresConnection(client, {\n        cursor: this.#config.cursor ?? null,\n      })\n      this.#connections.set(client, connection)\n\n      // The driver must take care of calling `onCreateConnection` when a new\n      // connection is created. The `pg` module doesn't provide an async hook\n      // for the connection creation. We need to call the method explicitly.\n      if (this.#config.onCreateConnection) {\n        await this.#config.onCreateConnection(connection)\n      }\n    }\n\n    if (this.#config.onReserveConnection) {\n      await this.#config.onReserveConnection(connection)\n    }\n\n    return connection\n  }\n\n  async beginTransaction(\n    connection: DatabaseConnection,\n    settings: TransactionSettings,\n  ): Promise<void> {\n    if (settings.isolationLevel || settings.accessMode) {\n      let sql = 'start transaction'\n\n      if (settings.isolationLevel) {\n        sql += ` isolation level ${settings.isolationLevel}`\n      }\n\n      if (settings.accessMode) {\n        sql += ` ${settings.accessMode}`\n      }\n\n      await connection.executeQuery(CompiledQuery.raw(sql))\n    } else {\n      await connection.executeQuery(CompiledQuery.raw('begin'))\n    }\n  }\n\n  async commitTransaction(connection: DatabaseConnection): Promise<void> {\n    await connection.executeQuery(CompiledQuery.raw('commit'))\n  }\n\n  async rollbackTransaction(connection: DatabaseConnection): Promise<void> {\n    await connection.executeQuery(CompiledQuery.raw('rollback'))\n  }\n\n  async savepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    await connection.executeQuery(\n      compileQuery(\n        parseSavepointCommand('savepoint', savepointName),\n        createQueryId(),\n      ),\n    )\n  }\n\n  async rollbackToSavepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    await connection.executeQuery(\n      compileQuery(\n        parseSavepointCommand('rollback to', savepointName),\n        createQueryId(),\n      ),\n    )\n  }\n\n  async releaseSavepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    await connection.executeQuery(\n      compileQuery(\n        parseSavepointCommand('release', savepointName),\n        createQueryId(),\n      ),\n    )\n  }\n\n  async releaseConnection(connection: PostgresConnection): Promise<void> {\n    connection[PRIVATE_RELEASE_METHOD]()\n  }\n\n  async destroy(): Promise<void> {\n    if (this.#pool) {\n      const pool = this.#pool\n      this.#pool = undefined\n      await pool.end()\n    }\n  }\n}\n\ninterface PostgresConnectionOptions {\n  cursor: PostgresCursorConstructor | null\n}\n\nclass PostgresConnection implements DatabaseConnection {\n  #client: PostgresPoolClient\n  #options: PostgresConnectionOptions\n\n  constructor(client: PostgresPoolClient, options: PostgresConnectionOptions) {\n    this.#client = client\n    this.#options = options\n  }\n\n  async executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {\n    try {\n      const { command, rowCount, rows } = await this.#client.query<O>(\n        compiledQuery.sql,\n        [...compiledQuery.parameters],\n      )\n\n      return {\n        numAffectedRows:\n          command === 'INSERT' ||\n          command === 'UPDATE' ||\n          command === 'DELETE' ||\n          command === 'MERGE'\n            ? BigInt(rowCount)\n            : undefined,\n        rows: rows ?? [],\n      }\n    } catch (err) {\n      throw extendStackTrace(err, new Error())\n    }\n  }\n\n  async *streamQuery<O>(\n    compiledQuery: CompiledQuery,\n    chunkSize: number,\n  ): AsyncIterableIterator<QueryResult<O>> {\n    if (!this.#options.cursor) {\n      throw new Error(\n        \"'cursor' is not present in your postgres dialect config. It's required to make streaming work in postgres.\",\n      )\n    }\n\n    if (!Number.isInteger(chunkSize) || chunkSize <= 0) {\n      throw new Error('chunkSize must be a positive integer')\n    }\n\n    const cursor = this.#client.query(\n      new this.#options.cursor<O>(\n        compiledQuery.sql,\n        compiledQuery.parameters.slice(),\n      ),\n    )\n\n    try {\n      while (true) {\n        const rows = await cursor.read(chunkSize)\n\n        if (rows.length === 0) {\n          break\n        }\n\n        yield {\n          rows,\n        }\n      }\n    } finally {\n      await cursor.close()\n    }\n  }\n\n  [PRIVATE_RELEASE_METHOD](): void {\n    this.#client.release()\n  }\n}\n"
  },
  {
    "path": "src/dialect/postgres/postgres-introspector.ts",
    "content": "import type {\n  DatabaseIntrospector,\n  DatabaseMetadata,\n  DatabaseMetadataOptions,\n  SchemaMetadata,\n  TableMetadata,\n} from '../database-introspector.js'\nimport {\n  DEFAULT_MIGRATION_LOCK_TABLE,\n  DEFAULT_MIGRATION_TABLE,\n} from '../../migration/migrator.js'\nimport type { Kysely } from '../../kysely.js'\nimport { freeze } from '../../util/object-utils.js'\nimport { sql } from '../../raw-builder/sql.js'\n\nexport class PostgresIntrospector implements DatabaseIntrospector {\n  readonly #db: Kysely<any>\n\n  constructor(db: Kysely<any>) {\n    this.#db = db\n  }\n\n  async getSchemas(): Promise<SchemaMetadata[]> {\n    let rawSchemas = await this.#db\n      .selectFrom('pg_catalog.pg_namespace')\n      .select('nspname')\n      .$castTo<RawSchemaMetadata>()\n      .execute()\n\n    return rawSchemas.map((it) => ({ name: it.nspname }))\n  }\n\n  async getTables(\n    options: DatabaseMetadataOptions = { withInternalKyselyTables: false },\n  ): Promise<TableMetadata[]> {\n    let query = this.#db\n      // column\n      .selectFrom('pg_catalog.pg_attribute as a')\n      // table\n      .innerJoin('pg_catalog.pg_class as c', 'a.attrelid', 'c.oid')\n      // table schema\n      .innerJoin('pg_catalog.pg_namespace as ns', 'c.relnamespace', 'ns.oid')\n      // column data type\n      .innerJoin('pg_catalog.pg_type as typ', 'a.atttypid', 'typ.oid')\n      // column data type schema\n      .innerJoin(\n        'pg_catalog.pg_namespace as dtns',\n        'typ.typnamespace',\n        'dtns.oid',\n      )\n      .select([\n        'a.attname as column',\n        'a.attnotnull as not_null',\n        'a.atthasdef as has_default',\n        'c.relname as table',\n        'c.relkind as table_type',\n        'ns.nspname as schema',\n        'typ.typname as type',\n        'dtns.nspname as type_schema',\n        sql<string | null>`col_description(a.attrelid, a.attnum)`.as(\n          'column_description',\n        ),\n        sql<\n          string | null\n        >`pg_get_serial_sequence(quote_ident(ns.nspname) || '.' || quote_ident(c.relname), a.attname)`.as(\n          'auto_incrementing',\n        ),\n      ])\n      .where('c.relkind', 'in', [\n        'r' /*regular table*/,\n        'v' /*view*/,\n        'p' /*partitioned table*/,\n      ])\n      .where('ns.nspname', '!~', '^pg_')\n      .where('ns.nspname', '!=', 'information_schema')\n      // Filter out internal cockroachdb schema\n      .where('ns.nspname', '!=', 'crdb_internal')\n      // Only schemas where we are allowed access\n      .where(sql<boolean>`has_schema_privilege(ns.nspname, 'USAGE')`)\n      // No system columns\n      .where('a.attnum', '>=', 0)\n      .where('a.attisdropped', '!=', true)\n      .orderBy('ns.nspname')\n      .orderBy('c.relname')\n      .orderBy('a.attnum')\n      .$castTo<RawColumnMetadata>()\n\n    if (!options.withInternalKyselyTables) {\n      query = query\n        .where('c.relname', '!=', DEFAULT_MIGRATION_TABLE)\n        .where('c.relname', '!=', DEFAULT_MIGRATION_LOCK_TABLE)\n    }\n\n    const rawColumns = await query.execute()\n\n    return this.#parseTableMetadata(rawColumns)\n  }\n\n  async getMetadata(\n    options?: DatabaseMetadataOptions,\n  ): Promise<DatabaseMetadata> {\n    return {\n      tables: await this.getTables(options),\n    }\n  }\n\n  #parseTableMetadata(columns: RawColumnMetadata[]): TableMetadata[] {\n    return columns.reduce<TableMetadata[]>((tables, it) => {\n      let table = tables.find(\n        (tbl) => tbl.name === it.table && tbl.schema === it.schema,\n      )\n\n      if (!table) {\n        table = freeze({\n          name: it.table,\n          isView: it.table_type === 'v',\n          schema: it.schema,\n          columns: [],\n        })\n\n        tables.push(table)\n      }\n\n      table.columns.push(\n        freeze({\n          name: it.column,\n          dataType: it.type,\n          dataTypeSchema: it.type_schema,\n          isNullable: !it.not_null,\n          isAutoIncrementing: it.auto_incrementing !== null,\n          hasDefaultValue: it.has_default,\n          comment: it.column_description ?? undefined,\n        }),\n      )\n\n      return tables\n    }, [])\n  }\n}\n\ninterface RawSchemaMetadata {\n  nspname: string\n}\n\ninterface RawColumnMetadata {\n  column: string\n  table: string\n  table_type: string\n  schema: string\n  not_null: boolean\n  has_default: boolean\n  type: string\n  type_schema: string\n  auto_incrementing: string | null\n  column_description: string | null\n}\n"
  },
  {
    "path": "src/dialect/postgres/postgres-query-compiler.ts",
    "content": "import { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js'\n\nconst ID_WRAP_REGEX = /\"/g\n\nexport class PostgresQueryCompiler extends DefaultQueryCompiler {\n  protected override sanitizeIdentifier(identifier: string): string {\n    return identifier.replace(ID_WRAP_REGEX, '\"\"')\n  }\n}\n"
  },
  {
    "path": "src/dialect/sqlite/sqlite-adapter.ts",
    "content": "import type { Kysely } from '../../kysely.js'\nimport { DialectAdapterBase } from '../dialect-adapter-base.js'\nimport type { MigrationLockOptions } from '../dialect-adapter.js'\n\nexport class SqliteAdapter extends DialectAdapterBase {\n  override get supportsTransactionalDdl(): boolean {\n    return false\n  }\n\n  override get supportsReturning(): boolean {\n    return true\n  }\n\n  override async acquireMigrationLock(\n    _db: Kysely<any>,\n    _opt: MigrationLockOptions,\n  ): Promise<void> {\n    // SQLite only has one connection that's reserved by the migration system\n    // for the whole time between acquireMigrationLock and releaseMigrationLock.\n    // We don't need to do anything here.\n  }\n\n  override async releaseMigrationLock(\n    _db: Kysely<any>,\n    _opt: MigrationLockOptions,\n  ): Promise<void> {\n    // SQLite only has one connection that's reserved by the migration system\n    // for the whole time between acquireMigrationLock and releaseMigrationLock.\n    // We don't need to do anything here.\n  }\n}\n"
  },
  {
    "path": "src/dialect/sqlite/sqlite-dialect-config.ts",
    "content": "import type { DatabaseConnection } from '../../driver/database-connection.js'\n\n/**\n * Config for the SQLite dialect.\n */\nexport interface SqliteDialectConfig {\n  /**\n   * An sqlite Database instance or a function that returns one.\n   *\n   * If a function is provided, it's called once when the first query is executed.\n   *\n   * https://github.com/JoshuaWise/better-sqlite3/blob/master/docs/api.md#new-databasepath-options\n   */\n  database: SqliteDatabase | (() => Promise<SqliteDatabase>)\n\n  /**\n   * Called once when the first query is executed.\n   *\n   * This is a Kysely specific feature and does not come from the `better-sqlite3` module.\n   */\n  onCreateConnection?: (connection: DatabaseConnection) => Promise<void>\n}\n\n/**\n * This interface is the subset of better-sqlite3 driver's `Database` class that\n * kysely needs.\n *\n * We don't use the type from `better-sqlite3` here to not have a dependency to it.\n *\n * https://github.com/JoshuaWise/better-sqlite3/blob/master/docs/api.md#new-databasepath-options\n */\nexport interface SqliteDatabase {\n  close(): void\n  prepare(sql: string): SqliteStatement\n}\n\nexport interface SqliteStatement {\n  readonly reader: boolean\n  all(parameters: ReadonlyArray<unknown>): unknown[]\n  run(parameters: ReadonlyArray<unknown>): {\n    changes: number | bigint\n    lastInsertRowid: number | bigint\n  }\n  iterate(parameters: ReadonlyArray<unknown>): IterableIterator<unknown>\n}\n"
  },
  {
    "path": "src/dialect/sqlite/sqlite-dialect.ts",
    "content": "import type { Driver } from '../../driver/driver.js'\nimport type { Kysely } from '../../kysely.js'\nimport type { QueryCompiler } from '../../query-compiler/query-compiler.js'\nimport type { Dialect } from '../dialect.js'\nimport type { DatabaseIntrospector } from '../database-introspector.js'\nimport { SqliteDriver } from './sqlite-driver.js'\nimport { SqliteQueryCompiler } from './sqlite-query-compiler.js'\nimport { SqliteIntrospector } from './sqlite-introspector.js'\nimport type { DialectAdapter } from '../dialect-adapter.js'\nimport { SqliteAdapter } from './sqlite-adapter.js'\nimport type { SqliteDialectConfig } from './sqlite-dialect-config.js'\nimport { freeze } from '../../util/object-utils.js'\n\n/**\n * SQLite dialect that uses the [better-sqlite3](https://github.com/JoshuaWise/better-sqlite3) library.\n *\n * The constructor takes an instance of {@link SqliteDialectConfig}.\n *\n * ```ts\n * import Database from 'better-sqlite3'\n *\n * new SqliteDialect({\n *   database: new Database('db.sqlite')\n * })\n * ```\n *\n * If you want the pool to only be created once it's first used, `database`\n * can be a function:\n *\n * ```ts\n * import Database from 'better-sqlite3'\n *\n * new SqliteDialect({\n *   database: async () => new Database('db.sqlite')\n * })\n * ```\n */\nexport class SqliteDialect implements Dialect {\n  readonly #config: SqliteDialectConfig\n\n  constructor(config: SqliteDialectConfig) {\n    this.#config = freeze({ ...config })\n  }\n\n  createDriver(): Driver {\n    return new SqliteDriver(this.#config)\n  }\n\n  createQueryCompiler(): QueryCompiler {\n    return new SqliteQueryCompiler()\n  }\n\n  createAdapter(): DialectAdapter {\n    return new SqliteAdapter()\n  }\n\n  createIntrospector(db: Kysely<any>): DatabaseIntrospector {\n    return new SqliteIntrospector(db)\n  }\n}\n"
  },
  {
    "path": "src/dialect/sqlite/sqlite-driver.ts",
    "content": "import type {\n  DatabaseConnection,\n  QueryResult,\n} from '../../driver/database-connection.js'\nimport type { Driver } from '../../driver/driver.js'\nimport { SelectQueryNode } from '../../operation-node/select-query-node.js'\nimport { parseSavepointCommand } from '../../parser/savepoint-parser.js'\nimport { CompiledQuery } from '../../query-compiler/compiled-query.js'\nimport type { QueryCompiler } from '../../query-compiler/query-compiler.js'\nimport { freeze, isFunction } from '../../util/object-utils.js'\nimport { createQueryId } from '../../util/query-id.js'\nimport type {\n  SqliteDatabase,\n  SqliteDialectConfig,\n} from './sqlite-dialect-config.js'\n\nexport class SqliteDriver implements Driver {\n  readonly #config: SqliteDialectConfig\n  readonly #connectionMutex = new ConnectionMutex()\n\n  #db?: SqliteDatabase\n  #connection?: DatabaseConnection\n\n  constructor(config: SqliteDialectConfig) {\n    this.#config = freeze({ ...config })\n  }\n\n  async init(): Promise<void> {\n    this.#db = isFunction(this.#config.database)\n      ? await this.#config.database()\n      : this.#config.database\n\n    this.#connection = new SqliteConnection(this.#db)\n\n    if (this.#config.onCreateConnection) {\n      await this.#config.onCreateConnection(this.#connection)\n    }\n  }\n\n  async acquireConnection(): Promise<DatabaseConnection> {\n    // SQLite only has one single connection. We use a mutex here to wait\n    // until the single connection has been released.\n    await this.#connectionMutex.lock()\n    return this.#connection!\n  }\n\n  async beginTransaction(connection: DatabaseConnection): Promise<void> {\n    await connection.executeQuery(CompiledQuery.raw('begin'))\n  }\n\n  async commitTransaction(connection: DatabaseConnection): Promise<void> {\n    await connection.executeQuery(CompiledQuery.raw('commit'))\n  }\n\n  async rollbackTransaction(connection: DatabaseConnection): Promise<void> {\n    await connection.executeQuery(CompiledQuery.raw('rollback'))\n  }\n\n  async savepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    await connection.executeQuery(\n      compileQuery(\n        parseSavepointCommand('savepoint', savepointName),\n        createQueryId(),\n      ),\n    )\n  }\n\n  async rollbackToSavepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    await connection.executeQuery(\n      compileQuery(\n        parseSavepointCommand('rollback to', savepointName),\n        createQueryId(),\n      ),\n    )\n  }\n\n  async releaseSavepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    await connection.executeQuery(\n      compileQuery(\n        parseSavepointCommand('release', savepointName),\n        createQueryId(),\n      ),\n    )\n  }\n\n  async releaseConnection(): Promise<void> {\n    this.#connectionMutex.unlock()\n  }\n\n  async destroy(): Promise<void> {\n    this.#db?.close()\n  }\n}\n\nclass SqliteConnection implements DatabaseConnection {\n  readonly #db: SqliteDatabase\n\n  constructor(db: SqliteDatabase) {\n    this.#db = db\n  }\n\n  executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {\n    const { sql, parameters } = compiledQuery\n    const stmt = this.#db.prepare(sql)\n\n    if (stmt.reader) {\n      return Promise.resolve({\n        rows: stmt.all(parameters) as O[],\n      })\n    }\n\n    const { changes, lastInsertRowid } = stmt.run(parameters)\n\n    return Promise.resolve({\n      numAffectedRows:\n        changes !== undefined && changes !== null ? BigInt(changes) : undefined,\n      insertId:\n        lastInsertRowid !== undefined && lastInsertRowid !== null\n          ? BigInt(lastInsertRowid)\n          : undefined,\n      rows: [],\n    })\n  }\n\n  async *streamQuery<R>(\n    compiledQuery: CompiledQuery,\n    _chunkSize: number,\n  ): AsyncIterableIterator<QueryResult<R>> {\n    const { sql, parameters, query } = compiledQuery\n    const stmt = this.#db.prepare(sql)\n    if (SelectQueryNode.is(query)) {\n      const iter = stmt.iterate(parameters) as IterableIterator<R>\n      for (const row of iter) {\n        yield {\n          rows: [row],\n        }\n      }\n    } else {\n      throw new Error('Sqlite driver only supports streaming of select queries')\n    }\n  }\n}\n\nclass ConnectionMutex {\n  #promise?: Promise<void>\n  #resolve?: () => void\n\n  async lock(): Promise<void> {\n    while (this.#promise) {\n      await this.#promise\n    }\n\n    this.#promise = new Promise((resolve) => {\n      this.#resolve = resolve\n    })\n  }\n\n  unlock(): void {\n    const resolve = this.#resolve\n\n    this.#promise = undefined\n    this.#resolve = undefined\n\n    resolve?.()\n  }\n}\n"
  },
  {
    "path": "src/dialect/sqlite/sqlite-introspector.ts",
    "content": "import type {\n  DatabaseIntrospector,\n  DatabaseMetadata,\n  DatabaseMetadataOptions,\n  SchemaMetadata,\n  TableMetadata,\n} from '../database-introspector.js'\nimport type { Kysely } from '../../kysely.js'\nimport {\n  DEFAULT_MIGRATION_LOCK_TABLE,\n  DEFAULT_MIGRATION_TABLE,\n} from '../../migration/migrator.js'\nimport { sql } from '../../raw-builder/sql.js'\nimport type { QueryCreator } from '../../query-creator.js'\n\ninterface SqliteSystemDatabase {\n  // https://www.sqlite.org/schematab.html#alternative_names\n  sqlite_master: SQliteMasterTable\n}\n\n// https://www.sqlite.org/schematab.html#interpretation_of_the_schema_table\ninterface SQliteMasterTable {\n  name: string\n  rootpage: number | null\n  sql: string\n  tbl_name: string\n  type: 'index' | 'table' | 'trigger' | 'view'\n}\n\n// https://www.sqlite.org/pragma.html#pragma_table_info\ninterface PragmaTableInfo {\n  cid: number\n  dflt_value: unknown\n  name: string\n  notnull: 0 | 1\n  pk: number\n  type: string\n}\n\nexport class SqliteIntrospector implements DatabaseIntrospector {\n  readonly #db: Kysely<SqliteSystemDatabase>\n\n  constructor(db: Kysely<any>) {\n    this.#db = db\n  }\n\n  async getSchemas(): Promise<SchemaMetadata[]> {\n    // Sqlite doesn't support schemas.\n    return []\n  }\n\n  async getTables(\n    options: DatabaseMetadataOptions = { withInternalKyselyTables: false },\n  ): Promise<TableMetadata[]> {\n    return await this.#getTableMetadata(options)\n  }\n\n  async getMetadata(\n    options?: DatabaseMetadataOptions,\n  ): Promise<DatabaseMetadata> {\n    return {\n      tables: await this.getTables(options),\n    }\n  }\n\n  #tablesQuery(\n    qb: QueryCreator<SqliteSystemDatabase> | Kysely<SqliteSystemDatabase>,\n    options: DatabaseMetadataOptions,\n  ) {\n    let tablesQuery = qb\n      .selectFrom('sqlite_master')\n      .where('type', 'in', ['table', 'view'])\n      .where('name', 'not like', 'sqlite_%')\n      .select(['name', 'sql', 'type'])\n      .orderBy('name')\n\n    if (!options.withInternalKyselyTables) {\n      tablesQuery = tablesQuery\n        .where('name', '!=', DEFAULT_MIGRATION_TABLE)\n        .where('name', '!=', DEFAULT_MIGRATION_LOCK_TABLE)\n    }\n    return tablesQuery\n  }\n\n  async #getTableMetadata(\n    options: DatabaseMetadataOptions,\n  ): Promise<TableMetadata[]> {\n    const tablesResult = await this.#tablesQuery(this.#db, options).execute()\n\n    const tableMetadata = await this.#db\n      .with('table_list', (qb) => this.#tablesQuery(qb, options))\n      .selectFrom([\n        'table_list as tl',\n        sql<PragmaTableInfo>`pragma_table_info(tl.name)`.as('p'),\n      ])\n      .select([\n        'tl.name as table',\n        'p.cid',\n        'p.name',\n        'p.type',\n        'p.notnull',\n        'p.dflt_value',\n        'p.pk',\n      ])\n      .orderBy('tl.name')\n      .orderBy('p.cid')\n      .execute()\n\n    const columnsByTable: Record<string, typeof tableMetadata> = {}\n    for (const row of tableMetadata) {\n      columnsByTable[row.table] ??= []\n      columnsByTable[row.table].push(row)\n    }\n\n    return tablesResult.map(({ name, sql, type }) => {\n      // // Try to find the name of the column that has `autoincrement` 🤦\n      let autoIncrementCol = sql\n        ?.split(/[\\(\\),]/)\n        ?.find((it) => it.toLowerCase().includes('autoincrement'))\n        ?.trimStart()\n        ?.split(/\\s+/)?.[0]\n        ?.replace(/[\"`]/g, '')\n\n      const columns = columnsByTable[name] ?? []\n\n      // Otherwise, check for an INTEGER PRIMARY KEY\n      // https://www.sqlite.org/autoinc.html\n      if (!autoIncrementCol) {\n        const pkCols = columns.filter((r) => r.pk > 0)\n        if (pkCols.length === 1 && pkCols[0].type.toLowerCase() === 'integer') {\n          autoIncrementCol = pkCols[0].name\n        }\n      }\n\n      return {\n        name: name,\n        isView: type === 'view',\n        columns: columns.map((col) => ({\n          name: col.name,\n          dataType: col.type,\n          isNullable: !col.notnull,\n          isAutoIncrementing: col.name === autoIncrementCol,\n          hasDefaultValue: col.dflt_value != null,\n          comment: undefined,\n        })),\n      }\n    })\n  }\n}\n"
  },
  {
    "path": "src/dialect/sqlite/sqlite-query-compiler.ts",
    "content": "import type { DefaultInsertValueNode } from '../../operation-node/default-insert-value-node.js'\nimport type { OrActionNode } from '../../operation-node/or-action-node.js'\nimport { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js'\n\nconst ID_WRAP_REGEX = /\"/g\n\nexport class SqliteQueryCompiler extends DefaultQueryCompiler {\n  protected override visitOrAction(node: OrActionNode): void {\n    this.append('or ')\n    this.append(node.action)\n  }\n\n  protected override getCurrentParameterPlaceholder(): string {\n    return '?'\n  }\n\n  protected override getLeftExplainOptionsWrapper(): string {\n    return ''\n  }\n\n  protected override getRightExplainOptionsWrapper(): string {\n    return ''\n  }\n\n  protected override getLeftIdentifierWrapper(): string {\n    return '\"'\n  }\n\n  protected override getRightIdentifierWrapper(): string {\n    return '\"'\n  }\n\n  protected override getAutoIncrement(): string {\n    return 'autoincrement'\n  }\n\n  protected override sanitizeIdentifier(identifier: string): string {\n    return identifier.replace(ID_WRAP_REGEX, '\"\"')\n  }\n\n  protected override visitDefaultInsertValue(_: DefaultInsertValueNode): void {\n    // sqlite doesn't support the `default` keyword in inserts.\n    this.append('null')\n  }\n}\n"
  },
  {
    "path": "src/driver/connection-provider.ts",
    "content": "import type { DatabaseConnection } from './database-connection.js'\n\nexport interface ConnectionProvider {\n  /**\n   * Provides a connection for the callback and takes care of disposing\n   * the connection after the callback has been run.\n   */\n  provideConnection<T>(\n    consumer: (connection: DatabaseConnection) => Promise<T>,\n  ): Promise<T>\n}\n"
  },
  {
    "path": "src/driver/database-connection.ts",
    "content": "import type { CompiledQuery } from '../query-compiler/compiled-query.js'\n\n/**\n * A single connection to the database engine.\n *\n * These are created by an instance of {@link Driver}.\n */\nexport interface DatabaseConnection {\n  executeQuery<R>(compiledQuery: CompiledQuery): Promise<QueryResult<R>>\n  streamQuery<R>(\n    compiledQuery: CompiledQuery,\n    chunkSize?: number,\n  ): AsyncIterableIterator<QueryResult<R>>\n}\n\nexport interface QueryResult<O> {\n  /**\n   * This is defined for insert, update, delete and merge queries and contains\n   * the number of rows the query inserted/updated/deleted.\n   */\n  readonly numAffectedRows?: bigint\n\n  /**\n   * This is defined for update queries and contains the number of rows\n   * the query changed.\n   *\n   * This is **optional** and only provided in dialects such as MySQL.\n   * You would probably use {@link numAffectedRows} in most cases.\n   */\n  readonly numChangedRows?: bigint\n\n  /**\n   * This is defined for insert queries on dialects that return\n   * the auto incrementing primary key from an insert.\n   */\n  readonly insertId?: bigint\n\n  /**\n   * The rows returned by the query. This is always defined and is\n   * empty if the query returned no rows.\n   */\n  readonly rows: O[]\n}\n"
  },
  {
    "path": "src/driver/default-connection-provider.ts",
    "content": "import type { DatabaseConnection } from './database-connection.js'\nimport type { ConnectionProvider } from './connection-provider.js'\nimport type { Driver } from './driver.js'\n\nexport class DefaultConnectionProvider implements ConnectionProvider {\n  readonly #driver: Driver\n\n  constructor(driver: Driver) {\n    this.#driver = driver\n  }\n\n  async provideConnection<T>(\n    consumer: (connection: DatabaseConnection) => Promise<T>,\n  ): Promise<T> {\n    const connection = await this.#driver.acquireConnection()\n\n    try {\n      return await consumer(connection)\n    } finally {\n      await this.#driver.releaseConnection(connection)\n    }\n  }\n}\n"
  },
  {
    "path": "src/driver/driver.ts",
    "content": "import type { QueryCompiler } from '../query-compiler/query-compiler.js'\nimport type { ArrayItemType } from '../util/type-utils.js'\nimport type { DatabaseConnection } from './database-connection.js'\n\n/**\n * A Driver creates and releases {@link DatabaseConnection | database connections}\n * and is also responsible for connection pooling (if the dialect supports pooling).\n */\nexport interface Driver {\n  /**\n   * Initializes the driver.\n   *\n   * After calling this method the driver should be usable and `acquireConnection` etc.\n   * methods should be callable.\n   */\n  init(): Promise<void>\n\n  /**\n   * Acquires a new connection from the pool.\n   */\n  acquireConnection(): Promise<DatabaseConnection>\n\n  /**\n   * Begins a transaction.\n   */\n  beginTransaction(\n    connection: DatabaseConnection,\n    settings: TransactionSettings,\n  ): Promise<void>\n\n  /**\n   * Commits a transaction.\n   */\n  commitTransaction(connection: DatabaseConnection): Promise<void>\n\n  /**\n   * Rolls back a transaction.\n   */\n  rollbackTransaction(connection: DatabaseConnection): Promise<void>\n\n  /**\n   * Establishses a new savepoint within a transaction.\n   */\n  savepoint?(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void>\n\n  /**\n   * Rolls back to a savepoint within a transaction.\n   */\n  rollbackToSavepoint?(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void>\n\n  /**\n   * Releases a savepoint within a transaction.\n   */\n  releaseSavepoint?(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void>\n\n  /**\n   * Releases a connection back to the pool.\n   */\n  releaseConnection(connection: DatabaseConnection): Promise<void>\n\n  /**\n   * Destroys the driver and releases all resources.\n   */\n  destroy(): Promise<void>\n}\n\nexport interface TransactionSettings {\n  readonly accessMode?: AccessMode\n  readonly isolationLevel?: IsolationLevel\n}\n\nexport const TRANSACTION_ACCESS_MODES = ['read only', 'read write'] as const\n\nexport type AccessMode = ArrayItemType<typeof TRANSACTION_ACCESS_MODES>\n\nexport const TRANSACTION_ISOLATION_LEVELS = [\n  'read uncommitted',\n  'read committed',\n  'repeatable read',\n  'serializable',\n  'snapshot',\n] as const\n\nexport type IsolationLevel = ArrayItemType<typeof TRANSACTION_ISOLATION_LEVELS>\n\nexport function validateTransactionSettings(\n  settings: TransactionSettings,\n): void {\n  if (\n    settings.accessMode &&\n    !TRANSACTION_ACCESS_MODES.includes(settings.accessMode)\n  ) {\n    throw new Error(`invalid transaction access mode ${settings.accessMode}`)\n  }\n\n  if (\n    settings.isolationLevel &&\n    !TRANSACTION_ISOLATION_LEVELS.includes(settings.isolationLevel)\n  ) {\n    throw new Error(\n      `invalid transaction isolation level ${settings.isolationLevel}`,\n    )\n  }\n}\n"
  },
  {
    "path": "src/driver/dummy-driver.ts",
    "content": "import type { DatabaseConnection, QueryResult } from './database-connection.js'\nimport type { Driver } from './driver.js'\n\n/**\n * A driver that does absolutely nothing.\n *\n * You can use this to create Kysely instances solely for building queries\n *\n * ### Examples\n *\n * This example creates a Kysely instance for building postgres queries:\n *\n * ```ts\n * import {\n *   DummyDriver,\n *   Kysely,\n *   PostgresAdapter,\n *   PostgresIntrospector,\n *   PostgresQueryCompiler\n * } from 'kysely'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: {\n *     createAdapter: () => new PostgresAdapter(),\n *     createDriver: () => new DummyDriver(),\n *     createIntrospector: (db: Kysely<any>) => new PostgresIntrospector(db),\n *     createQueryCompiler: () => new PostgresQueryCompiler(),\n *   },\n * })\n * ```\n *\n * You can use it to build a query and compile it to SQL but trying to\n * execute the query will throw an error.\n *\n * ```ts\n * const { sql } = db.selectFrom('person').selectAll().compile()\n * console.log(sql) // select * from \"person\"\n * ```\n */\nexport class DummyDriver implements Driver {\n  async init(): Promise<void> {\n    // Nothing to do here.\n  }\n\n  async acquireConnection(): Promise<DatabaseConnection> {\n    return new DummyConnection()\n  }\n\n  async beginTransaction(): Promise<void> {\n    // Nothing to do here.\n  }\n\n  async commitTransaction(): Promise<void> {\n    // Nothing to do here.\n  }\n\n  async rollbackTransaction(): Promise<void> {\n    // Nothing to do here.\n  }\n\n  async releaseConnection(): Promise<void> {\n    // Nothing to do here.\n  }\n\n  async destroy(): Promise<void> {\n    // Nothing to do here.\n  }\n\n  async releaseSavepoint(): Promise<void> {\n    // Nothing to do here.\n  }\n\n  async rollbackToSavepoint(): Promise<void> {\n    // Nothing to do here.\n  }\n\n  async savepoint(): Promise<void> {\n    // Nothing to do here.\n  }\n}\n\nclass DummyConnection implements DatabaseConnection {\n  async executeQuery<R>(): Promise<QueryResult<R>> {\n    return {\n      rows: [],\n    }\n  }\n\n  async *streamQuery<R>(): AsyncIterableIterator<QueryResult<R>> {\n    // Nothing to do here.\n  }\n}\n"
  },
  {
    "path": "src/driver/runtime-driver.ts",
    "content": "import type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { QueryCompiler } from '../query-compiler/query-compiler.js'\nimport type { Log } from '../util/log.js'\nimport { performanceNow } from '../util/performance-now.js'\nimport type { DatabaseConnection, QueryResult } from './database-connection.js'\nimport type { Driver, TransactionSettings } from './driver.js'\n\n/**\n * A small wrapper around {@link Driver} that makes sure the driver is\n * initialized before it is used, only initialized and destroyed\n * once etc.\n */\nexport class RuntimeDriver implements Driver {\n  readonly #driver: Driver\n  readonly #log: Log\n\n  #initPromise?: Promise<void>\n  #initDone: boolean\n  #destroyPromise?: Promise<void>\n  #connections = new WeakSet<DatabaseConnection>()\n\n  constructor(driver: Driver, log: Log) {\n    this.#initDone = false\n    this.#driver = driver\n    this.#log = log\n  }\n\n  async init(): Promise<void> {\n    if (this.#destroyPromise) {\n      throw new Error('driver has already been destroyed')\n    }\n\n    if (!this.#initPromise) {\n      this.#initPromise = this.#driver\n        .init()\n        .then(() => {\n          this.#initDone = true\n        })\n        .catch((err) => {\n          this.#initPromise = undefined\n          return Promise.reject(err)\n        })\n    }\n\n    await this.#initPromise\n  }\n\n  async acquireConnection(): Promise<DatabaseConnection> {\n    if (this.#destroyPromise) {\n      throw new Error('driver has already been destroyed')\n    }\n\n    if (!this.#initDone) {\n      await this.init()\n    }\n\n    const connection = await this.#driver.acquireConnection()\n\n    if (!this.#connections.has(connection)) {\n      if (this.#needsLogging()) {\n        this.#addLogging(connection)\n      }\n\n      this.#connections.add(connection)\n    }\n\n    return connection\n  }\n\n  async releaseConnection(connection: DatabaseConnection): Promise<void> {\n    await this.#driver.releaseConnection(connection)\n  }\n\n  beginTransaction(\n    connection: DatabaseConnection,\n    settings: TransactionSettings,\n  ): Promise<void> {\n    return this.#driver.beginTransaction(connection, settings)\n  }\n\n  commitTransaction(connection: DatabaseConnection): Promise<void> {\n    return this.#driver.commitTransaction(connection)\n  }\n\n  rollbackTransaction(connection: DatabaseConnection): Promise<void> {\n    return this.#driver.rollbackTransaction(connection)\n  }\n\n  savepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    if (this.#driver.savepoint) {\n      return this.#driver.savepoint(connection, savepointName, compileQuery)\n    }\n\n    throw new Error('The `savepoint` method is not supported by this driver')\n  }\n\n  rollbackToSavepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    if (this.#driver.rollbackToSavepoint) {\n      return this.#driver.rollbackToSavepoint(\n        connection,\n        savepointName,\n        compileQuery,\n      )\n    }\n\n    throw new Error(\n      'The `rollbackToSavepoint` method is not supported by this driver',\n    )\n  }\n\n  releaseSavepoint(\n    connection: DatabaseConnection,\n    savepointName: string,\n    compileQuery: QueryCompiler['compileQuery'],\n  ): Promise<void> {\n    if (this.#driver.releaseSavepoint) {\n      return this.#driver.releaseSavepoint(\n        connection,\n        savepointName,\n        compileQuery,\n      )\n    }\n\n    throw new Error(\n      'The `releaseSavepoint` method is not supported by this driver',\n    )\n  }\n\n  async destroy(): Promise<void> {\n    if (!this.#initPromise) {\n      return\n    }\n\n    await this.#initPromise\n\n    if (!this.#destroyPromise) {\n      this.#destroyPromise = this.#driver.destroy().catch((err) => {\n        this.#destroyPromise = undefined\n        return Promise.reject(err)\n      })\n    }\n\n    await this.#destroyPromise\n  }\n\n  #needsLogging(): boolean {\n    return (\n      this.#log.isLevelEnabled('query') || this.#log.isLevelEnabled('error')\n    )\n  }\n\n  // This method monkey patches the database connection's executeQuery method\n  // by adding logging code around it. Monkey patching is not pretty, but it's\n  // the best option in this case.\n  #addLogging(connection: DatabaseConnection): void {\n    const executeQuery = connection.executeQuery\n    const streamQuery = connection.streamQuery\n    const dis = this\n\n    connection.executeQuery = async (\n      compiledQuery,\n    ): Promise<QueryResult<any>> => {\n      let caughtError: unknown\n      const startTime = performanceNow()\n\n      try {\n        return await executeQuery.call(connection, compiledQuery)\n      } catch (error) {\n        caughtError = error\n        await dis.#logError(error, compiledQuery, startTime)\n        throw error\n      } finally {\n        if (!caughtError) {\n          await dis.#logQuery(compiledQuery, startTime)\n        }\n      }\n    }\n\n    connection.streamQuery = async function* (\n      compiledQuery,\n      chunkSize,\n    ): AsyncIterableIterator<QueryResult<any>> {\n      let caughtError: unknown\n      const startTime = performanceNow()\n\n      try {\n        for await (const result of streamQuery.call(\n          connection,\n          compiledQuery,\n          chunkSize,\n        )) {\n          yield result\n        }\n      } catch (error) {\n        caughtError = error\n        await dis.#logError(error, compiledQuery, startTime)\n        throw error\n      } finally {\n        if (!caughtError) {\n          await dis.#logQuery(compiledQuery, startTime, true)\n        }\n      }\n    }\n  }\n\n  async #logError(\n    error: unknown,\n    compiledQuery: CompiledQuery,\n    startTime: number,\n  ): Promise<void> {\n    await this.#log.error(() => ({\n      level: 'error',\n      error,\n      query: compiledQuery,\n      queryDurationMillis: this.#calculateDurationMillis(startTime),\n    }))\n  }\n\n  async #logQuery(\n    compiledQuery: CompiledQuery,\n    startTime: number,\n    isStream = false,\n  ): Promise<void> {\n    await this.#log.query(() => ({\n      level: 'query',\n      isStream,\n      query: compiledQuery,\n      queryDurationMillis: this.#calculateDurationMillis(startTime),\n    }))\n  }\n\n  #calculateDurationMillis(startTime: number): number {\n    return performanceNow() - startTime\n  }\n}\n"
  },
  {
    "path": "src/driver/single-connection-provider.ts",
    "content": "import type { DatabaseConnection } from './database-connection.js'\nimport type { ConnectionProvider } from './connection-provider.js'\n\nconst ignoreError = () => {}\n\nexport class SingleConnectionProvider implements ConnectionProvider {\n  readonly #connection: DatabaseConnection\n  #runningPromise?: Promise<any>\n\n  constructor(connection: DatabaseConnection) {\n    this.#connection = connection\n  }\n\n  async provideConnection<T>(\n    consumer: (connection: DatabaseConnection) => Promise<T>,\n  ): Promise<T> {\n    while (this.#runningPromise) {\n      await this.#runningPromise.catch(ignoreError)\n    }\n\n    // `#runningPromise` must be set to undefined before it's\n    // resolved or rejected. Otherwise the while loop above\n    // will misbehave.\n    this.#runningPromise = this.#run(consumer).finally(() => {\n      this.#runningPromise = undefined\n    })\n\n    return this.#runningPromise\n  }\n\n  // Run the runner in an async function to make sure it doesn't\n  // throw synchronous errors.\n  async #run<T>(\n    runner: (connection: DatabaseConnection) => Promise<T>,\n  ): Promise<T> {\n    return await runner(this.#connection)\n  }\n}\n"
  },
  {
    "path": "src/dynamic/dynamic-reference-builder.ts",
    "content": "import {\n  isOperationNodeSource,\n  type OperationNodeSource,\n} from '../operation-node/operation-node-source.js'\nimport type { SimpleReferenceExpressionNode } from '../operation-node/simple-reference-expression-node.js'\nimport { parseSimpleReferenceExpression } from '../parser/reference-parser.js'\nimport { isObject, isString } from '../util/object-utils.js'\n\nexport class DynamicReferenceBuilder<\n  R extends string = never,\n> implements OperationNodeSource {\n  readonly #dynamicReference: string\n\n  get dynamicReference(): string {\n    return this.#dynamicReference\n  }\n\n  /**\n   * @private\n   *\n   * This needs to be here just so that the typings work. Without this\n   * the generated .d.ts file contains no reference to the type param R\n   * which causes this type to be equal to DynamicReferenceBuilder with\n   * any R.\n   */\n  protected get refType(): R {\n    return undefined as unknown as R\n  }\n\n  constructor(reference: string) {\n    this.#dynamicReference = reference\n  }\n\n  toOperationNode(): SimpleReferenceExpressionNode {\n    return parseSimpleReferenceExpression(this.#dynamicReference)\n  }\n}\n\nexport function isDynamicReferenceBuilder(\n  obj: unknown,\n): obj is DynamicReferenceBuilder<any> {\n  return (\n    isObject(obj) &&\n    isOperationNodeSource(obj) &&\n    isString(obj.dynamicReference)\n  )\n}\n"
  },
  {
    "path": "src/dynamic/dynamic-table-builder.ts",
    "content": "import { AliasNode } from '../operation-node/alias-node.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport {\n  isOperationNodeSource,\n  type OperationNodeSource,\n} from '../operation-node/operation-node-source.js'\nimport { parseTable } from '../parser/table-parser.js'\nimport { isObject, isString } from '../util/object-utils.js'\n\nexport class DynamicTableBuilder<T extends string> {\n  readonly #table: T\n\n  get table(): T {\n    return this.#table\n  }\n\n  constructor(table: T) {\n    this.#table = table\n  }\n\n  as<A extends string>(alias: A): AliasedDynamicTableBuilder<T, A> {\n    return new AliasedDynamicTableBuilder(this.#table, alias)\n  }\n}\n\nexport class AliasedDynamicTableBuilder<\n  T extends string,\n  A extends string,\n> implements OperationNodeSource {\n  readonly #table: T\n  readonly #alias: A\n\n  get table(): T {\n    return this.#table\n  }\n\n  get alias(): A {\n    return this.#alias\n  }\n\n  constructor(table: T, alias: A) {\n    this.#table = table\n    this.#alias = alias\n  }\n\n  toOperationNode(): AliasNode {\n    return AliasNode.create(\n      parseTable(this.#table),\n      IdentifierNode.create(this.#alias),\n    )\n  }\n}\n\nexport function isAliasedDynamicTableBuilder(\n  obj: unknown,\n): obj is AliasedDynamicTableBuilder<any, any> {\n  return (\n    isObject(obj) &&\n    isOperationNodeSource(obj) &&\n    isString(obj.table) &&\n    isString(obj.alias)\n  )\n}\n"
  },
  {
    "path": "src/dynamic/dynamic.ts",
    "content": "import { DynamicReferenceBuilder } from './dynamic-reference-builder.js'\nimport { DynamicTableBuilder } from './dynamic-table-builder.js'\n\nexport class DynamicModule<DB> {\n  /**\n   * Creates a dynamic reference to a column that is not know at compile time.\n   *\n   * Kysely is built in a way that by default you can't refer to tables or columns\n   * that are not actually visible in the current query and context. This is all\n   * done by TypeScript at compile time, which means that you need to know the\n   * columns and tables at compile time. This is not always the case of course.\n   *\n   * This method is meant to be used in those cases where the column names\n   * come from the user input or are not otherwise known at compile time.\n   *\n   * WARNING! Unlike values, column names are not escaped by the database engine\n   * or Kysely and if you pass in unchecked column names using this method, you\n   * create an SQL injection vulnerability. Always __always__ validate the user\n   * input before passing it to this method.\n   *\n   * There are couple of examples below for some use cases, but you can pass\n   * `ref` to other methods as well. If the types allow you to pass a `ref`\n   * value to some place, it should work.\n   *\n   * ### Examples\n   *\n   * Filter by a column not know at compile time:\n   *\n   * ```ts\n   * async function someQuery(filterColumn: string, filterValue: string) {\n   *   const { ref } = db.dynamic\n   *\n   *   return await db\n   *     .selectFrom('person')\n   *     .selectAll()\n   *     .where(ref(filterColumn), '=', filterValue)\n   *     .execute()\n   * }\n   *\n   * someQuery('first_name', 'Arnold')\n   * someQuery('person.last_name', 'Aniston')\n   * ```\n   *\n   * Order by a column not know at compile time:\n   *\n   * ```ts\n   * async function someQuery(orderBy: string) {\n   *   const { ref } = db.dynamic\n   *\n   *   return await db\n   *     .selectFrom('person')\n   *     .select('person.first_name as fn')\n   *     .orderBy(ref(orderBy))\n   *     .execute()\n   * }\n   *\n   * someQuery('fn')\n   * ```\n   *\n   * In this example we add selections dynamically:\n   *\n   * ```ts\n   * const { ref } = db.dynamic\n   *\n   * // Some column name provided by the user. Value not known at compile time.\n   * const columnFromUserInput: PossibleColumns = 'birthdate';\n   *\n   * // A type that lists all possible values `columnFromUserInput` can have.\n   * // You can use `keyof Person` if any column of an interface is allowed.\n   * type PossibleColumns = 'last_name' | 'first_name' | 'birthdate'\n   *\n   * const [person] = await db.selectFrom('person')\n   *   .select([\n   *     ref<PossibleColumns>(columnFromUserInput),\n   *     'id'\n   *   ])\n   *   .execute()\n   *\n   * // The resulting type contains all `PossibleColumns` as optional fields\n   * // because we cannot know which field was actually selected before\n   * // running the code.\n   * const lastName: string | null | undefined = person?.last_name\n   * const firstName: string | undefined = person?.first_name\n   * const birthDate: Date | null | undefined = person?.birthdate\n   *\n   * // The result type also contains the compile time selection `id`.\n   * person?.id\n   * ```\n   */\n  ref<R extends string = never>(reference: string): DynamicReferenceBuilder<R> {\n    return new DynamicReferenceBuilder<R>(reference)\n  }\n\n  /**\n   * Creates a table reference to a table that's not fully known at compile time.\n   *\n   * The type `T` is allowed to be a union of multiple tables.\n   *\n   * <!-- siteExample(\"select\", \"Generic find query\", 130) -->\n   *\n   * A generic type-safe helper function for finding a row by a column value:\n   *\n   * ```ts\n   * import { SelectType } from 'kysely'\n   * import { Database } from 'type-editor'\n   *\n   * async function getRowByColumn<\n   *   T extends keyof Database,\n   *   C extends keyof Database[T] & string,\n   *   V extends SelectType<Database[T][C]>,\n   * >(t: T, c: C, v: V) {\n   *   // We need to use the dynamic module since the table name\n   *   // is not known at compile time.\n   *   const { table, ref } = db.dynamic\n   *\n   *   return await db\n   *     .selectFrom(table(t).as('t'))\n   *     .selectAll()\n   *     .where(ref(c), '=', v)\n   *     .orderBy('t.id')\n   *     .executeTakeFirstOrThrow()\n   * }\n   *\n   * const person = await getRowByColumn('person', 'first_name', 'Arnold')\n   * ```\n   */\n  table<T extends keyof DB & string>(table: T): DynamicTableBuilder<T> {\n    return new DynamicTableBuilder<T>(table)\n  }\n}\n"
  },
  {
    "path": "src/expression/expression-builder.ts",
    "content": "import {\n  type SelectQueryBuilder,\n  createSelectQueryBuilder,\n} from '../query-builder/select-query-builder.js'\nimport { SelectQueryNode } from '../operation-node/select-query-node.js'\nimport {\n  parseTableExpressionOrList,\n  type TableExpressionOrList,\n  parseTable,\n} from '../parser/table-parser.js'\nimport { WithSchemaPlugin } from '../plugin/with-schema/with-schema-plugin.js'\nimport { createQueryId } from '../util/query-id.js'\nimport {\n  createFunctionModule,\n  type FunctionModule,\n} from '../query-builder/function-module.js'\nimport {\n  type ExtractTypeFromReferenceExpression,\n  parseJSONReference,\n  parseReferenceExpression,\n  parseStringReference,\n  type ReferenceExpression,\n  type SimpleReferenceExpression,\n  type StringReference,\n} from '../parser/reference-parser.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport {\n  type BinaryOperatorExpression,\n  type FilterObject,\n  type OperandValueExpression,\n  type OperandValueExpressionOrList,\n  parseFilterList,\n  parseFilterObject,\n  parseValueBinaryOperation,\n  parseValueBinaryOperationOrExpression,\n} from '../parser/binary-operation-parser.js'\nimport type { Expression } from './expression.js'\nimport { ParensNode } from '../operation-node/parens-node.js'\nimport { ExpressionWrapper } from './expression-wrapper.js'\nimport {\n  type ComparisonOperator,\n  type JSONOperatorWith$,\n  OperatorNode,\n  type UnaryOperator,\n} from '../operation-node/operator-node.js'\nimport type { IsNever, SqlBool } from '../util/type-utils.js'\nimport { parseUnaryOperation } from '../parser/unary-operation-parser.js'\nimport {\n  type ExtractTypeFromValueExpression,\n  parseSafeImmediateValue,\n  parseValueExpression,\n} from '../parser/value-parser.js'\nimport { NOOP_QUERY_EXECUTOR } from '../query-executor/noop-query-executor.js'\nimport { CaseBuilder } from '../query-builder/case-builder.js'\nimport { CaseNode } from '../operation-node/case-node.js'\nimport { isReadonlyArray, isUndefined } from '../util/object-utils.js'\nimport { JSONPathBuilder } from '../query-builder/json-path-builder.js'\nimport type { OperandExpression } from '../parser/expression-parser.js'\nimport { BinaryOperationNode } from '../operation-node/binary-operation-node.js'\nimport { AndNode } from '../operation-node/and-node.js'\nimport type {\n  RefTuple2,\n  RefTuple3,\n  RefTuple4,\n  RefTuple5,\n  ValTuple2,\n  ValTuple3,\n  ValTuple4,\n  ValTuple5,\n} from '../parser/tuple-parser.js'\nimport { TupleNode } from '../operation-node/tuple-node.js'\nimport type { Selectable } from '../util/column-type.js'\nimport { JSONPathNode } from '../operation-node/json-path-node.js'\nimport type { KyselyTypeError } from '../util/type-error.js'\nimport {\n  type DataTypeExpression,\n  parseDataTypeExpression,\n} from '../parser/data-type-parser.js'\nimport { CastNode } from '../operation-node/cast-node.js'\nimport type { SelectFrom } from '../parser/select-from-parser.js'\n\nexport interface ExpressionBuilder<DB, TB extends keyof DB> {\n  /**\n   * Creates a binary expression.\n   *\n   * This function returns an {@link Expression} and can be used pretty much anywhere.\n   * See the examples for a couple of possible use cases.\n   *\n   * ### Examples\n   *\n   * A simple comparison:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where((eb) => eb('first_name', '=', 'Jennifer'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where \"first_name\" = $1\n   * ```\n   *\n   * By default the third argument is interpreted as a value. To pass in\n   * a column reference, you can use {@link ref}:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where((eb) => eb('first_name', '=', eb.ref('last_name')))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where \"first_name\" = \"last_name\"\n   * ```\n   *\n   * In the following example `eb` is used to increment an integer column:\n   *\n   * ```ts\n   * await db.updateTable('person')\n   *   .set((eb) => ({\n   *     age: eb('age', '+', 1)\n   *   }))\n   *   .where('id', '=', 3)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * update \"person\"\n   * set \"age\" = \"age\" + $1\n   * where \"id\" = $2\n   * ```\n   *\n   * As always, expressions can be nested. Both the first and the third argument\n   * can be any expression:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where((eb) => eb(\n   *     eb.fn<string>('lower', ['first_name']),\n   *     'in',\n   *     eb.selectFrom('pet')\n   *       .select('pet.name')\n   *       .where('pet.species', '=', 'cat')\n   *   ))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where lower(\"first_name\") in (\n   *   select \"pet\".\"name\"\n   *   from \"pet\"\n   *   where \"pet\".\"species\" = $1\n   * )\n   * ```\n   */\n  <\n    RE extends ReferenceExpression<DB, TB>,\n    OP extends BinaryOperatorExpression,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: OP,\n    rhs: VE,\n  ): ExpressionWrapper<\n    DB,\n    TB,\n    OP extends ComparisonOperator\n      ? SqlBool\n      : OP extends Expression<infer T>\n        ? unknown extends T\n          ? SqlBool\n          : T\n        : ExtractTypeFromReferenceExpression<DB, TB, RE>\n  >\n\n  /**\n   * Returns a copy of `this` expression builder, for destructuring purposes.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .where(({ eb, exists, selectFrom }) =>\n   *     eb('first_name', '=', 'Jennifer').and(exists(\n   *       selectFrom('pet').whereRef('owner_id', '=', 'person.id').select('pet.id')\n   *     ))\n   *   )\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\" where \"first_name\" = $1 and exists (\n   *   select \"pet.id\" from \"pet\" where \"owner_id\" = \"person.id\"\n   * )\n   * ```\n   */\n  get eb(): ExpressionBuilder<DB, TB>\n\n  /**\n   * Returns a {@link FunctionModule} that can be used to write type safe function\n   * calls.\n   *\n   * The difference between this and {@link Kysely.fn} is that this one is more\n   * type safe. You can only refer to columns visible to the part of the query\n   * you are building. {@link Kysely.fn} allows you to refer to columns in any\n   * table of the database even if it doesn't produce valid SQL.\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .select((eb) => [\n   *     'person.id',\n   *     eb.fn.count('pet.id').as('pet_count')\n   *   ])\n   *   .groupBy('person.id')\n   *   .having((eb) => eb.fn.count('pet.id'), '>', 10)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"id\", count(\"pet\".\"id\") as \"pet_count\"\n   * from \"person\"\n   * inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * group by \"person\".\"id\"\n   * having count(\"pet\".\"id\") > $1\n   * ```\n   */\n  get fn(): FunctionModule<DB, TB>\n\n  /**\n   * Creates a subquery.\n   *\n   * The query builder returned by this method is typed in a way that you can refer to\n   * all tables of the parent query in addition to the subquery's tables.\n   *\n   * This method accepts all the same inputs as {@link QueryCreator.selectFrom}.\n   *\n   * ### Examples\n   *\n   * This example shows that you can refer to both `pet.owner_id` and `person.id`\n   * columns from the subquery. This is needed to be able to create correlated\n   * subqueries:\n   *\n   * ```ts\n   * const result = await db.selectFrom('pet')\n   *   .select((eb) => [\n   *     'pet.name',\n   *     eb.selectFrom('person')\n   *       .whereRef('person.id', '=', 'pet.owner_id')\n   *       .select('person.first_name')\n   *       .as('owner_name')\n   *   ])\n   *   .execute()\n   *\n   * console.log(result[0]?.owner_name)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   \"pet\".\"name\",\n   *   ( select \"person\".\"first_name\"\n   *     from \"person\"\n   *     where \"person\".\"id\" = \"pet\".\"owner_id\"\n   *   ) as \"owner_name\"\n   * from \"pet\"\n   * ```\n   *\n   * You can use a normal query in place of `(qb) => qb.selectFrom(...)` but in\n   * that case Kysely typings wouldn't allow you to reference `pet.owner_id`\n   * because `pet` is not joined to that query.\n   */\n  selectFrom<TE extends TableExpressionOrList<DB, TB>>(\n    from: TE,\n  ): SelectFrom<DB, TB, TE>\n\n  /**\n   * Creates a `case` statement/operator.\n   *\n   * ### Examples\n   *\n   * Kitchen sink example with 2 flavors of `case` operator:\n   *\n   * ```ts\n   * const { title, name } = await db\n   *   .selectFrom('person')\n   *   .where('id', '=', 123)\n   *   .select((eb) => [\n   *     eb.fn.coalesce('last_name', 'first_name').as('name'),\n   *     eb\n   *       .case()\n   *       .when('gender', '=', 'male')\n   *       .then('Mr.')\n   *       .when('gender', '=', 'female')\n   *       .then(\n   *         eb\n   *           .case('marital_status')\n   *           .when('single')\n   *           .then('Ms.')\n   *           .else('Mrs.')\n   *           .end()\n   *       )\n   *       .end()\n   *       .as('title'),\n   *   ])\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   coalesce(\"last_name\", \"first_name\") as \"name\",\n   *   case\n   *     when \"gender\" = $1 then $2\n   *     when \"gender\" = $3 then\n   *       case \"marital_status\"\n   *         when $4 then $5\n   *         else $6\n   *       end\n   *   end as \"title\"\n   * from \"person\"\n   * where \"id\" = $7\n   * ```\n   */\n  case(): CaseBuilder<DB, TB>\n\n  case<C extends SimpleReferenceExpression<DB, TB>>(\n    column: C,\n  ): CaseBuilder<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, C>>\n\n  case<E extends Expression<any>>(\n    expression: E,\n  ): CaseBuilder<DB, TB, ExtractTypeFromValueExpression<E>>\n\n  /**\n   * This method can be used to reference columns within the query's context. For\n   * a non-type-safe version of this method see {@link sql}'s version.\n   *\n   * Additionally, this method can be used to reference nested JSON properties or\n   * array elements. See {@link JSONPathBuilder} for more information. For regular\n   * JSON path expressions you can use {@link jsonPath}.\n   *\n   * ### Examples\n   *\n   * By default the third argument of binary expressions is a value.\n   * This function can be used to pass in a column reference instead:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where((eb) => eb.or([\n   *     eb('first_name', '=', eb.ref('last_name')),\n   *     eb('first_name', '=', eb.ref('middle_name'))\n   *   ]))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*\n   * from \"person\"\n   * where \"first_name\" = \"last_name\" or \"first_name\" = \"middle_name\"\n   * ```\n   *\n   * In the next example we use the `ref` method to reference columns of the virtual\n   * table `excluded` in a type-safe way to create an upsert operation:\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .values({\n   *     id: 3,\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston',\n   *     gender: 'female',\n   *   })\n   *   .onConflict((oc) => oc\n   *     .column('id')\n   *     .doUpdateSet(({ ref }) => ({\n   *       first_name: ref('excluded.first_name'),\n   *       last_name: ref('excluded.last_name'),\n   *       gender: ref('excluded.gender'),\n   *     }))\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"id\", \"first_name\", \"last_name\", \"gender\")\n   * values ($1, $2, $3, $4)\n   * on conflict (\"id\") do update set\n   *   \"first_name\" = \"excluded\".\"first_name\",\n   *   \"last_name\" = \"excluded\".\"last_name\",\n   *   \"gender\" = \"excluded\".\"gender\"\n   * ```\n   *\n   * In the next example we use `ref` in a raw sql expression. Unless you want\n   * to be as type-safe as possible, this is probably overkill:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.updateTable('pet')\n   *   .set((eb) => ({\n   *     name: sql<string>`concat(${eb.ref('pet.name')}, ${' the animal'})`\n   *   }))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * update \"pet\" set \"name\" = concat(\"pet\".\"name\", $1)\n   * ```\n   *\n   * In the next example we use `ref` to reference a nested JSON property:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .where(({ eb, ref }) => eb(\n   *     ref('profile', '->').key('addresses').at(0).key('city'),\n   *     '=',\n   *     'San Diego'\n   *   ))\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\" where \"profile\"->'addresses'->0->'city' = $1\n   * ```\n   *\n   * You can also compile to a JSON path expression by using the `->$`or `->>$` operator:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .select(({ ref }) =>\n   *     ref('profile', '->$')\n   *       .key('addresses')\n   *       .at('last')\n   *       .key('city')\n   *       .as('current_city')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * select `profile`->'$.addresses[last].city' as `current_city` from `person`\n   * ```\n   */\n  ref<RE extends StringReference<DB, TB>>(\n    reference: RE,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>\n\n  ref<RE extends StringReference<DB, TB>>(\n    reference: RE,\n    op: JSONOperatorWith$,\n  ): JSONPathBuilder<ExtractTypeFromReferenceExpression<DB, TB, RE>>\n\n  /**\n   * Creates a JSON path expression with provided column as root document (the $).\n   *\n   * For a JSON reference expression, see {@link ref}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.updateTable('person')\n   *   .set('profile', (eb) => eb.fn('json_set', [\n   *     'profile',\n   *     eb.jsonPath<'profile'>().key('addresses').at('last').key('city'),\n   *     eb.val('San Diego')\n   *   ]))\n   *   .where('id', '=', 3)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * update `person`\n   * set `profile` = json_set(`profile`, '$.addresses[last].city', $1)\n   * where `id` = $2\n   * ```\n   */\n  jsonPath<$ extends StringReference<DB, TB> = never>(): IsNever<$> extends true\n    ? KyselyTypeError<\"You must provide a column reference as this method's $ generic\">\n    : JSONPathBuilder<ExtractTypeFromReferenceExpression<DB, TB, $>>\n\n  /**\n   * Creates a table reference.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   * import type { Pet } from 'type-editor' // imaginary module\n   *\n   * const result = await db.selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .select(eb => [\n   *     'person.id',\n   *     sql<Pet[]>`jsonb_agg(${eb.table('pet')})`.as('pets')\n   *   ])\n   *   .groupBy('person.id')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"id\", jsonb_agg(\"pet\") as \"pets\"\n   * from \"person\"\n   * inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * group by \"person\".\"id\"\n   * ```\n   *\n   * If you need a column reference, use {@link ref}.\n   */\n  table<T extends TB & string>(\n    table: T,\n  ): ExpressionWrapper<DB, TB, Selectable<DB[T]>>\n\n  /**\n   * Returns a value expression.\n   *\n   * This can be used to pass in a value where a reference is taken by default.\n   *\n   * This function returns an {@link Expression} and can be used pretty much anywhere.\n   *\n   * ### Examples\n   *\n   * Binary expressions take a reference by default as the first argument. `val` could\n   * be used to pass in a value instead:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where((eb) => eb(\n   *     eb.val('cat'),\n   *     '=',\n   *     eb.fn.any(\n   *       eb.selectFrom('pet')\n   *         .select('species')\n   *         .whereRef('owner_id', '=', 'person.id')\n   *     )\n   *   ))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where $1 = any(\n   *   select \"species\"\n   *   from \"pet\"\n   *   where \"owner_id\" = \"person\".\"id\"\n   * )\n   * ```\n   */\n  val<VE>(\n    value: VE,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromValueExpression<VE>>\n\n  /**\n   * Creates a tuple expression.\n   *\n   * This creates a tuple using column references by default. See {@link tuple}\n   * if you need to create value tuples.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where(({ eb, refTuple, tuple }) => eb(\n   *     refTuple('first_name', 'last_name'),\n   *     'in',\n   *     [\n   *       tuple('Jennifer', 'Aniston'),\n   *       tuple('Sylvester', 'Stallone')\n   *     ]\n   *   ))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   \"person\".*\n   * from\n   *   \"person\"\n   * where\n   *   (\"first_name\", \"last_name\")\n   *   in\n   *   (\n   *     ($1, $2),\n   *     ($3, $4)\n   *   )\n   * ```\n   *\n   * In the next example a reference tuple is compared to a subquery. Note that\n   * in this case you need to use the {@link @SelectQueryBuilder.$asTuple | $asTuple}\n   * function:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where(({ eb, refTuple, selectFrom }) => eb(\n   *     refTuple('first_name', 'last_name'),\n   *     'in',\n   *     selectFrom('pet')\n   *       .select(['name', 'species'])\n   *       .where('species', '!=', 'cat')\n   *       .$asTuple('name', 'species')\n   *   ))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   \"person\".*\n   * from\n   *   \"person\"\n   * where\n   *   (\"first_name\", \"last_name\")\n   *   in\n   *   (\n   *     select \"name\", \"species\"\n   *     from \"pet\"\n   *     where \"species\" != $1\n   *   )\n   * ```\n   */\n  refTuple<\n    R1 extends ReferenceExpression<DB, TB>,\n    R2 extends ReferenceExpression<DB, TB>,\n  >(\n    value1: R1,\n    value2: R2,\n  ): ExpressionWrapper<DB, TB, RefTuple2<DB, TB, R1, R2>>\n\n  refTuple<\n    R1 extends ReferenceExpression<DB, TB>,\n    R2 extends ReferenceExpression<DB, TB>,\n    R3 extends ReferenceExpression<DB, TB>,\n  >(\n    value1: R1,\n    value2: R2,\n    value3: R3,\n  ): ExpressionWrapper<DB, TB, RefTuple3<DB, TB, R1, R2, R3>>\n\n  refTuple<\n    R1 extends ReferenceExpression<DB, TB>,\n    R2 extends ReferenceExpression<DB, TB>,\n    R3 extends ReferenceExpression<DB, TB>,\n    R4 extends ReferenceExpression<DB, TB>,\n  >(\n    value1: R1,\n    value2: R2,\n    value3: R3,\n    value4: R4,\n  ): ExpressionWrapper<DB, TB, RefTuple4<DB, TB, R1, R2, R3, R4>>\n\n  refTuple<\n    R1 extends ReferenceExpression<DB, TB>,\n    R2 extends ReferenceExpression<DB, TB>,\n    R3 extends ReferenceExpression<DB, TB>,\n    R4 extends ReferenceExpression<DB, TB>,\n    R5 extends ReferenceExpression<DB, TB>,\n  >(\n    value1: R1,\n    value2: R2,\n    value3: R3,\n    value4: R4,\n    value5: R5,\n  ): ExpressionWrapper<DB, TB, RefTuple5<DB, TB, R1, R2, R3, R4, R5>>\n\n  /**\n   * Creates a value tuple expression.\n   *\n   * This creates a tuple using values by default. See {@link refTuple} if you need to create\n   * tuples using column references.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where(({ eb, refTuple, tuple }) => eb(\n   *     refTuple('first_name', 'last_name'),\n   *     'in',\n   *     [\n   *       tuple('Jennifer', 'Aniston'),\n   *       tuple('Sylvester', 'Stallone')\n   *     ]\n   *   ))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   \"person\".*\n   * from\n   *   \"person\"\n   * where\n   *   (\"first_name\", \"last_name\")\n   *   in\n   *   (\n   *     ($1, $2),\n   *     ($3, $4)\n   *   )\n   * ```\n   */\n  tuple<V1, V2>(\n    value1: V1,\n    value2: V2,\n  ): ExpressionWrapper<DB, TB, ValTuple2<V1, V2>>\n\n  tuple<V1, V2, V3>(\n    value1: V1,\n    value2: V2,\n    value3: V3,\n  ): ExpressionWrapper<DB, TB, ValTuple3<V1, V2, V3>>\n\n  tuple<V1, V2, V3, V4>(\n    value1: V1,\n    value2: V2,\n    value3: V3,\n    value4: V4,\n  ): ExpressionWrapper<DB, TB, ValTuple4<V1, V2, V3, V4>>\n\n  tuple<V1, V2, V3, V4, V5>(\n    value1: V1,\n    value2: V2,\n    value3: V3,\n    value4: V4,\n    value5: V5,\n  ): ExpressionWrapper<DB, TB, ValTuple5<V1, V2, V3, V4, V5>>\n\n  /**\n   * Returns a literal value expression.\n   *\n   * Just like `val` but creates a literal value that gets merged in the SQL.\n   * To prevent SQL injections, only `boolean`, `number` and `null` values\n   * are accepted. If you need `string` or other literals, use `sql.lit` instead.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .select((eb) => eb.lit(1).as('one'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select 1 as \"one\" from \"person\"\n   * ```\n   */\n  lit<VE extends number | boolean | null>(\n    literal: VE,\n  ): ExpressionWrapper<DB, TB, VE>\n\n  /**\n   * Creates an unary expression.\n   *\n   * This function returns an {@link Expression} and can be used pretty much anywhere.\n   * See the examples for a couple of possible use cases.\n   *\n   * @see {@link not}, {@link exists} and {@link neg}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .select((eb) => [\n   *     'first_name',\n   *     eb.unary('-', 'age').as('negative_age')\n   *   ])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\", -\"age\"\n   * from \"person\"\n   * ```\n   */\n  unary<RE extends ReferenceExpression<DB, TB>>(\n    op: UnaryOperator,\n    expr: RE,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>\n\n  /**\n   * Creates a `not` operation.\n   *\n   * A shortcut for `unary('not', expr)`.\n   *\n   * @see {@link unary}\n   */\n  not<RE extends ReferenceExpression<DB, TB>>(\n    expr: RE,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>\n\n  /**\n   * Creates an `exists` operation.\n   *\n   * A shortcut for `unary('exists', expr)`.\n   *\n   * @see {@link unary}\n   */\n  exists<RE extends ReferenceExpression<DB, TB>>(\n    expr: RE,\n  ): ExpressionWrapper<DB, TB, SqlBool>\n\n  /**\n   * Creates a negation operation.\n   *\n   * A shortcut for `unary('-', expr)`.\n   *\n   * @see {@link unary}\n   */\n  neg<RE extends ReferenceExpression<DB, TB>>(\n    expr: RE,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>\n\n  /**\n   * Creates a `between` expression.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where((eb) => eb.between('age', 40, 60))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\" where \"age\" between $1 and $2\n   * ```\n   */\n  between<\n    RE extends ReferenceExpression<DB, TB>,\n    SE extends OperandValueExpression<DB, TB, RE>,\n    EE extends OperandValueExpression<DB, TB, RE>,\n  >(\n    expr: RE,\n    start: SE,\n    end: EE,\n  ): ExpressionWrapper<DB, TB, SqlBool>\n\n  /**\n   * Creates a `between symmetric` expression.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where((eb) => eb.betweenSymmetric('age', 40, 60))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\" where \"age\" between symmetric $1 and $2\n   * ```\n   */\n  betweenSymmetric<\n    RE extends ReferenceExpression<DB, TB>,\n    SE extends OperandValueExpression<DB, TB, RE>,\n    EE extends OperandValueExpression<DB, TB, RE>,\n  >(\n    expr: RE,\n    start: SE,\n    end: EE,\n  ): ExpressionWrapper<DB, TB, SqlBool>\n\n  /**\n   * Combines two or more expressions using the logical `and` operator.\n   *\n   * An empty array produces a `true` expression.\n   *\n   * This function returns an {@link Expression} and can be used pretty much anywhere.\n   * See the examples for a couple of possible use cases.\n   *\n   * ### Examples\n   *\n   * In this example we use `and` to create a `WHERE expr1 AND expr2 AND expr3`\n   * statement:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where((eb) => eb.and([\n   *     eb('first_name', '=', 'Jennifer'),\n   *     eb('first_name', '=', 'Arnold'),\n   *     eb('first_name', '=', 'Sylvester')\n   *   ]))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*\n   * from \"person\"\n   * where (\n   *   \"first_name\" = $1\n   *   and \"first_name\" = $2\n   *   and \"first_name\" = $3\n   * )\n   * ```\n   *\n   * Optionally you can use the simpler object notation if you only need\n   * equality comparisons:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where((eb) => eb.and({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   }))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*\n   * from \"person\"\n   * where (\n   *   \"first_name\" = $1\n   *   and \"last_name\" = $2\n   * )\n   * ```\n   */\n  and<E extends OperandExpression<SqlBool>>(\n    exprs: ReadonlyArray<E>,\n  ): ExpressionWrapper<DB, TB, SqlBool>\n\n  and<E extends Readonly<FilterObject<DB, TB>>>(\n    exprs: E,\n  ): ExpressionWrapper<DB, TB, SqlBool>\n\n  /**\n   * Combines two or more expressions using the logical `or` operator.\n   *\n   * An empty array produces a `false` expression.\n   *\n   * This function returns an {@link Expression} and can be used pretty much anywhere.\n   * See the examples for a couple of possible use cases.\n   *\n   * ### Examples\n   *\n   * In this example we use `or` to create a `WHERE expr1 OR expr2 OR expr3`\n   * statement:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where((eb) => eb.or([\n   *     eb('first_name', '=', 'Jennifer'),\n   *     eb('first_name', '=', 'Arnold'),\n   *     eb('first_name', '=', 'Sylvester')\n   *   ]))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*\n   * from \"person\"\n   * where (\n   *   \"first_name\" = $1\n   *   or \"first_name\" = $2\n   *   or \"first_name\" = $3\n   * )\n   * ```\n   *\n   * Optionally you can use the simpler object notation if you only need\n   * equality comparisons:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where((eb) => eb.or({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   }))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*\n   * from \"person\"\n   * where (\n   *   \"first_name\" = $1\n   *   or \"last_name\" = $2\n   * )\n   * ```\n   */\n  or<E extends OperandExpression<SqlBool>>(\n    exprs: ReadonlyArray<E>,\n  ): ExpressionWrapper<DB, TB, SqlBool>\n\n  or<E extends Readonly<FilterObject<DB, TB>>>(\n    exprs: E,\n  ): ExpressionWrapper<DB, TB, SqlBool>\n\n  /**\n   * Wraps the expression in parentheses.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where((eb) => eb(eb.parens('age', '+', 1), '/', 100), '<', 0.1)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*\n   * from \"person\"\n   * where (\"age\" + $1) / $2 < $3\n   * ```\n   *\n   * You can also pass in any expression as the only argument:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where((eb) => eb.parens(\n   *     eb('age', '=', 1).or('age', '=', 2)\n   *   ).and(\n   *     eb('first_name', '=', 'Jennifer').or('first_name', '=', 'Arnold')\n   *   ))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*\n   * from \"person\"\n   * where (\"age\" = $1 or \"age\" = $2) and (\"first_name\" = $3 or \"first_name\" = $4)\n   * ```\n   */\n  parens<\n    RE extends ReferenceExpression<DB, TB>,\n    OP extends BinaryOperatorExpression,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: OP,\n    rhs: VE,\n  ): ExpressionWrapper<\n    DB,\n    TB,\n    OP extends ComparisonOperator\n      ? SqlBool\n      : ExtractTypeFromReferenceExpression<DB, TB, RE>\n  >\n\n  parens<T>(expr: Expression<T>): ExpressionWrapper<DB, TB, T>\n\n  /**\n   * Creates a `cast(expr as dataType)` expression.\n   *\n   * Since Kysely can't know the mapping between JavaScript and database types,\n   * you need to provide both explicitly.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .select((eb) => [\n   *     'id',\n   *     'first_name',\n   *     eb.cast<number>('age', 'integer').as('age')\n   *   ])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select cast(\"age\" as integer) as \"age\"\n   * from \"person\"\n   * ```\n   */\n  cast<T, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(\n    expr: RE,\n    dataType: DataTypeExpression,\n  ): ExpressionWrapper<DB, TB, T>\n\n  /**\n   * See {@link QueryCreator.withSchema}\n   *\n   * @deprecated Will be removed in kysely 0.25.0.\n   */\n  withSchema(schema: string): ExpressionBuilder<DB, TB>\n}\n\nexport function createExpressionBuilder<DB, TB extends keyof DB>(\n  executor: QueryExecutor = NOOP_QUERY_EXECUTOR,\n): ExpressionBuilder<DB, TB> {\n  function binary<\n    RE extends ReferenceExpression<DB, TB>,\n    OP extends BinaryOperatorExpression,\n  >(\n    lhs: RE,\n    op: OP,\n    rhs: OperandValueExpressionOrList<DB, TB, RE>,\n  ): ExpressionWrapper<\n    DB,\n    TB,\n    OP extends ComparisonOperator\n      ? SqlBool\n      : OP extends Expression<infer T>\n        ? unknown extends T\n          ? SqlBool\n          : T\n        : ExtractTypeFromReferenceExpression<DB, TB, RE>\n  > {\n    return new ExpressionWrapper(parseValueBinaryOperation(lhs, op, rhs))\n  }\n\n  function unary<RE extends ReferenceExpression<DB, TB>>(\n    op: UnaryOperator,\n    expr: RE,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>> {\n    return new ExpressionWrapper(parseUnaryOperation(op, expr))\n  }\n\n  const eb = Object.assign(binary, {\n    fn: undefined! as FunctionModule<DB, TB>,\n    eb: undefined! as ExpressionBuilder<DB, TB>,\n\n    selectFrom(table: TableExpressionOrList<DB, TB>): any {\n      return createSelectQueryBuilder({\n        queryId: createQueryId(),\n        executor,\n        queryNode: SelectQueryNode.createFrom(\n          parseTableExpressionOrList(table),\n        ),\n      })\n    },\n\n    case<RE extends ReferenceExpression<DB, TB>>(\n      reference?: RE,\n    ): CaseBuilder<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>> {\n      return new CaseBuilder({\n        node: CaseNode.create(\n          isUndefined(reference)\n            ? undefined\n            : parseReferenceExpression(reference),\n        ),\n      })\n    },\n\n    ref<RE extends StringReference<DB, TB>>(\n      reference: RE,\n      op?: JSONOperatorWith$,\n    ): any {\n      if (isUndefined(op)) {\n        return new ExpressionWrapper(parseStringReference(reference))\n      }\n\n      return new JSONPathBuilder(parseJSONReference(reference, op))\n    },\n\n    jsonPath<\n      $ extends StringReference<DB, TB> = never,\n    >(): IsNever<$> extends true\n      ? KyselyTypeError<\"You must provide a column reference as this method's $ generic\">\n      : JSONPathBuilder<ExtractTypeFromReferenceExpression<DB, TB, $>> {\n      return new JSONPathBuilder(JSONPathNode.create()) as any\n    },\n\n    table<T extends TB & string>(\n      table: T,\n    ): ExpressionWrapper<DB, TB, Selectable<DB[T]>> {\n      return new ExpressionWrapper(parseTable(table))\n    },\n\n    val<VE>(\n      value: VE,\n    ): ExpressionWrapper<DB, TB, ExtractTypeFromValueExpression<VE>> {\n      return new ExpressionWrapper(parseValueExpression(value))\n    },\n\n    refTuple(\n      ...values: ReadonlyArray<ReferenceExpression<any, any>>\n    ): ExpressionWrapper<DB, TB, any> {\n      return new ExpressionWrapper(\n        TupleNode.create(values.map(parseReferenceExpression)),\n      )\n    },\n\n    tuple(...values: ReadonlyArray<unknown>): ExpressionWrapper<DB, TB, any> {\n      return new ExpressionWrapper(\n        TupleNode.create(values.map(parseValueExpression)),\n      )\n    },\n\n    lit<VE extends number | boolean | null>(\n      value: VE,\n    ): ExpressionWrapper<DB, TB, VE> {\n      return new ExpressionWrapper(parseSafeImmediateValue(value))\n    },\n\n    unary,\n\n    not<RE extends ReferenceExpression<DB, TB>>(\n      expr: RE,\n    ): ExpressionWrapper<\n      DB,\n      TB,\n      ExtractTypeFromReferenceExpression<DB, TB, RE>\n    > {\n      return unary('not', expr)\n    },\n\n    exists<RE extends ReferenceExpression<DB, TB>>(\n      expr: RE,\n    ): ExpressionWrapper<DB, TB, SqlBool> {\n      return unary('exists', expr)\n    },\n\n    neg<RE extends ReferenceExpression<DB, TB>>(\n      expr: RE,\n    ): ExpressionWrapper<\n      DB,\n      TB,\n      ExtractTypeFromReferenceExpression<DB, TB, RE>\n    > {\n      return unary('-', expr)\n    },\n\n    between<RE extends ReferenceExpression<DB, TB>>(\n      expr: RE,\n      start: OperandValueExpression<DB, TB, RE>,\n      end: OperandValueExpression<DB, TB, RE>,\n    ): ExpressionWrapper<DB, TB, SqlBool> {\n      return new ExpressionWrapper(\n        BinaryOperationNode.create(\n          parseReferenceExpression(expr),\n          OperatorNode.create('between'),\n          AndNode.create(\n            parseValueExpression(start),\n            parseValueExpression(end),\n          ),\n        ),\n      )\n    },\n\n    betweenSymmetric<RE extends ReferenceExpression<DB, TB>>(\n      expr: RE,\n      start: OperandValueExpression<DB, TB, RE>,\n      end: OperandValueExpression<DB, TB, RE>,\n    ): ExpressionWrapper<DB, TB, SqlBool> {\n      return new ExpressionWrapper(\n        BinaryOperationNode.create(\n          parseReferenceExpression(expr),\n          OperatorNode.create('between symmetric'),\n          AndNode.create(\n            parseValueExpression(start),\n            parseValueExpression(end),\n          ),\n        ),\n      )\n    },\n\n    and(\n      exprs:\n        | ReadonlyArray<OperandExpression<SqlBool>>\n        | Readonly<FilterObject<DB, TB>>,\n    ): ExpressionWrapper<DB, TB, SqlBool> {\n      if (isReadonlyArray(exprs)) {\n        return new ExpressionWrapper(parseFilterList(exprs, 'and'))\n      }\n\n      return new ExpressionWrapper(parseFilterObject(exprs, 'and'))\n    },\n\n    or(\n      exprs:\n        | ReadonlyArray<OperandExpression<SqlBool>>\n        | Readonly<FilterObject<DB, TB>>,\n    ): ExpressionWrapper<DB, TB, SqlBool> {\n      if (isReadonlyArray(exprs)) {\n        return new ExpressionWrapper(parseFilterList(exprs, 'or'))\n      }\n\n      return new ExpressionWrapper(parseFilterObject(exprs, 'or'))\n    },\n\n    parens(...args: any[]) {\n      const node = parseValueBinaryOperationOrExpression(args)\n\n      if (ParensNode.is(node)) {\n        // No double wrapping.\n        return new ExpressionWrapper(node)\n      } else {\n        return new ExpressionWrapper(ParensNode.create(node))\n      }\n    },\n\n    cast<T, RE extends ReferenceExpression<DB, TB>>(\n      expr: RE,\n      dataType: DataTypeExpression,\n    ) {\n      return new ExpressionWrapper<DB, TB, T>(\n        CastNode.create(\n          parseReferenceExpression(expr),\n          parseDataTypeExpression(dataType),\n        ),\n      )\n    },\n\n    withSchema(schema: string): ExpressionBuilder<DB, TB> {\n      return createExpressionBuilder(\n        executor.withPluginAtFront(new WithSchemaPlugin(schema)),\n      )\n    },\n  })\n\n  eb.fn = createFunctionModule()\n  eb.eb = eb\n\n  return eb\n}\n\nexport function expressionBuilder<DB, TB extends keyof DB>(\n  _: SelectQueryBuilder<DB, TB, any>,\n): ExpressionBuilder<DB, TB>\n\nexport function expressionBuilder<\n  DB,\n  TB extends keyof DB = never,\n>(): ExpressionBuilder<DB, TB>\n\nexport function expressionBuilder<DB, TB extends keyof DB>(\n  _?: unknown,\n): ExpressionBuilder<DB, TB> {\n  return createExpressionBuilder()\n}\n"
  },
  {
    "path": "src/expression/expression-wrapper.ts",
    "content": "import { AliasNode } from '../operation-node/alias-node.js'\nimport { AndNode } from '../operation-node/and-node.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport { isOperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport { OrNode } from '../operation-node/or-node.js'\nimport { ParensNode } from '../operation-node/parens-node.js'\nimport {\n  type ComparisonOperatorExpression,\n  type OperandValueExpressionOrList,\n  parseValueBinaryOperationOrExpression,\n} from '../parser/binary-operation-parser.js'\nimport type { OperandExpression } from '../parser/expression-parser.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport type { KyselyTypeError } from '../util/type-error.js'\nimport type { SqlBool } from '../util/type-utils.js'\nimport type {\n  AliasableExpression,\n  AliasedExpression,\n  Expression,\n} from './expression.js'\n\nexport class ExpressionWrapper<\n  DB,\n  TB extends keyof DB,\n  T,\n> implements AliasableExpression<T> {\n  readonly #node: OperationNode\n\n  constructor(node: OperationNode) {\n    this.#node = node\n  }\n\n  /** @private */\n  get expressionType(): T | undefined {\n    return undefined\n  }\n\n  /**\n   * Returns an aliased version of the expression.\n   *\n   * ### Examples\n   *\n   * In addition to slapping `as \"the_alias\"` to the end of the SQL,\n   * this method also provides strict typing:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select((eb) =>\n   *     eb('first_name', '=', 'Jennifer').as('is_jennifer')\n   *   )\n   *   .executeTakeFirstOrThrow()\n   *\n   * // `is_jennifer: SqlBool` field exists in the result type.\n   * console.log(result.is_jennifer)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\" = $1 as \"is_jennifer\"\n   * from \"person\"\n   * ```\n   */\n  as<A extends string>(alias: A): AliasedExpression<T, A>\n\n  as<A extends string>(alias: Expression<unknown>): AliasedExpression<T, A>\n\n  as(alias: string | Expression<any>): AliasedExpression<T, string> {\n    return new AliasedExpressionWrapper(this, alias)\n  }\n\n  /**\n   * Combines `this` and another expression using `OR`.\n   *\n   * Also see {@link ExpressionBuilder.or}\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where(eb => eb('first_name', '=', 'Jennifer')\n   *     .or('first_name', '=', 'Arnold')\n   *     .or('first_name', '=', 'Sylvester')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where (\n   *   \"first_name\" = $1\n   *   or \"first_name\" = $2\n   *   or \"first_name\" = $3\n   * )\n   * ```\n   *\n   * You can also pass any expression as the only argument to\n   * this method:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where(eb => eb('first_name', '=', 'Jennifer')\n   *     .or(eb('first_name', '=', 'Sylvester').and('last_name', '=', 'Stallone'))\n   *     .or(eb.exists(\n   *       eb.selectFrom('pet')\n   *         .select('id')\n   *         .whereRef('pet.owner_id', '=', 'person.id')\n   *     ))\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where (\n   *   \"first_name\" = $1\n   *   or (\"first_name\" = $2 and \"last_name\" = $3)\n   *   or exists (\n   *     select \"id\"\n   *     from \"pet\"\n   *     where \"pet\".\"owner_id\" = \"person\".\"id\"\n   *   )\n   * )\n   * ```\n   */\n  or<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): T extends SqlBool\n    ? OrWrapper<DB, TB, SqlBool>\n    : KyselyTypeError<'or() method can only be called on boolean expressions'>\n\n  or<E extends OperandExpression<SqlBool>>(\n    expression: E,\n  ): T extends SqlBool\n    ? OrWrapper<DB, TB, SqlBool>\n    : KyselyTypeError<'or() method can only be called on boolean expressions'>\n\n  or(...args: any[]): any {\n    return new OrWrapper(\n      OrNode.create(this.#node, parseValueBinaryOperationOrExpression(args)),\n    )\n  }\n\n  /**\n   * Combines `this` and another expression using `AND`.\n   *\n   * Also see {@link ExpressionBuilder.and}\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where(eb => eb('first_name', '=', 'Jennifer')\n   *     .and('last_name', '=', 'Aniston')\n   *     .and('age', '>', 40)\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where (\n   *   \"first_name\" = $1\n   *   and \"last_name\" = $2\n   *   and \"age\" > $3\n   * )\n   * ```\n   *\n   * You can also pass any expression as the only argument to\n   * this method:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .selectAll()\n   *   .where(eb => eb('first_name', '=', 'Jennifer')\n   *     .and(eb('first_name', '=', 'Sylvester').or('last_name', '=', 'Stallone'))\n   *     .and(eb.exists(\n   *       eb.selectFrom('pet')\n   *         .select('id')\n   *         .whereRef('pet.owner_id', '=', 'person.id')\n   *     ))\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where (\n   *   \"first_name\" = $1\n   *   and (\"first_name\" = $2 or \"last_name\" = $3)\n   *   and exists (\n   *     select \"id\"\n   *     from \"pet\"\n   *     where \"pet\".\"owner_id\" = \"person\".\"id\"\n   *   )\n   * )\n   * ```\n   */\n  and<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): T extends SqlBool\n    ? AndWrapper<DB, TB, SqlBool>\n    : KyselyTypeError<'and() method can only be called on boolean expressions'>\n\n  and<E extends OperandExpression<SqlBool>>(\n    expression: E,\n  ): T extends SqlBool\n    ? AndWrapper<DB, TB, SqlBool>\n    : KyselyTypeError<'and() method can only be called on boolean expressions'>\n\n  and(...args: any[]): any {\n    return new AndWrapper(\n      AndNode.create(this.#node, parseValueBinaryOperationOrExpression(args)),\n    )\n  }\n\n  /**\n   * Change the output type of the expression.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `ExpressionWrapper` with a new output type.\n   */\n  $castTo<C>(): ExpressionWrapper<DB, TB, C> {\n    return new ExpressionWrapper(this.#node)\n  }\n\n  /**\n   * Omit null from the expression's type.\n   *\n   * This function can be useful in cases where you know an expression can't be\n   * null, but Kysely is unable to infer it.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of `this` with a new output type.\n   */\n  $notNull(): ExpressionWrapper<DB, TB, Exclude<T, null>> {\n    return new ExpressionWrapper(this.#node)\n  }\n\n  toOperationNode(): OperationNode {\n    return this.#node\n  }\n}\n\nexport class AliasedExpressionWrapper<\n  T,\n  A extends string,\n> implements AliasedExpression<T, A> {\n  readonly #expr: Expression<T>\n  readonly #alias: A | Expression<unknown>\n\n  constructor(expr: Expression<T>, alias: A | Expression<unknown>) {\n    this.#expr = expr\n    this.#alias = alias\n  }\n\n  /** @private */\n  get expression(): Expression<T> {\n    return this.#expr\n  }\n\n  /** @private */\n  get alias(): A | Expression<unknown> {\n    return this.#alias\n  }\n\n  toOperationNode(): AliasNode {\n    return AliasNode.create(\n      this.#expr.toOperationNode(),\n      isOperationNodeSource(this.#alias)\n        ? this.#alias.toOperationNode()\n        : IdentifierNode.create(this.#alias),\n    )\n  }\n}\n\nexport class OrWrapper<\n  DB,\n  TB extends keyof DB,\n  T extends SqlBool,\n> implements AliasableExpression<T> {\n  readonly #node: OrNode\n\n  constructor(node: OrNode) {\n    this.#node = node\n  }\n\n  /** @private */\n  get expressionType(): T | undefined {\n    return undefined\n  }\n\n  /**\n   * Returns an aliased version of the expression.\n   *\n   * In addition to slapping `as \"the_alias\"` to the end of the SQL,\n   * this method also provides strict typing:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select(eb =>\n   *     eb('first_name', '=', 'Jennifer')\n   *       .or('first_name', '=', 'Sylvester')\n   *       .as('is_jennifer_or_sylvester')\n   *   )\n   *   .executeTakeFirstOrThrow()\n   *\n   * // `is_jennifer_or_sylvester: SqlBool` field exists in the result type.\n   * console.log(result.is_jennifer_or_sylvester)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\" = $1 or \"first_name\" = $2 as \"is_jennifer_or_sylvester\"\n   * from \"person\"\n   * ```\n   */\n  as<A extends string>(alias: A): AliasedExpression<T, A>\n\n  as<A extends string>(alias: Expression<unknown>): AliasedExpression<T, A>\n\n  as(alias: string | Expression<any>): AliasedExpression<T, string> {\n    return new AliasedExpressionWrapper(this, alias)\n  }\n\n  /**\n   * Combines `this` and another expression using `OR`.\n   *\n   * See {@link ExpressionWrapper.or} for examples.\n   */\n  or<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): OrWrapper<DB, TB, T>\n\n  or<E extends OperandExpression<SqlBool>>(expression: E): OrWrapper<DB, TB, T>\n\n  or(...args: any[]): any {\n    return new OrWrapper(\n      OrNode.create(this.#node, parseValueBinaryOperationOrExpression(args)),\n    )\n  }\n\n  /**\n   * Change the output type of the expression.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `OrWrapper` with a new output type.\n   */\n  $castTo<C extends SqlBool>(): OrWrapper<DB, TB, C> {\n    return new OrWrapper(this.#node)\n  }\n\n  toOperationNode(): ParensNode {\n    return ParensNode.create(this.#node)\n  }\n}\n\nexport class AndWrapper<\n  DB,\n  TB extends keyof DB,\n  T extends SqlBool,\n> implements AliasableExpression<T> {\n  readonly #node: AndNode\n\n  constructor(node: AndNode) {\n    this.#node = node\n  }\n\n  /** @private */\n  get expressionType(): T | undefined {\n    return undefined\n  }\n\n  /**\n   * Returns an aliased version of the expression.\n   *\n   * In addition to slapping `as \"the_alias\"` to the end of the SQL,\n   * this method also provides strict typing:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select(eb =>\n   *     eb('first_name', '=', 'Jennifer')\n   *       .and('last_name', '=', 'Aniston')\n   *       .as('is_jennifer_aniston')\n   *   )\n   *   .executeTakeFirstOrThrow()\n   *\n   * // `is_jennifer_aniston: SqlBool` field exists in the result type.\n   * console.log(result.is_jennifer_aniston)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\" = $1 and \"first_name\" = $2 as \"is_jennifer_aniston\"\n   * from \"person\"\n   * ```\n   */\n  as<A extends string>(alias: A): AliasedExpression<T, A>\n\n  as<A extends string>(alias: Expression<unknown>): AliasedExpression<T, A>\n\n  as(alias: string | Expression<any>): AliasedExpression<T, string> {\n    return new AliasedExpressionWrapper(this, alias)\n  }\n\n  /**\n   * Combines `this` and another expression using `AND`.\n   *\n   * See {@link ExpressionWrapper.and} for examples.\n   */\n  and<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): AndWrapper<DB, TB, T>\n\n  and<E extends OperandExpression<SqlBool>>(\n    expression: E,\n  ): AndWrapper<DB, TB, T>\n\n  and(...args: any[]): any {\n    return new AndWrapper(\n      AndNode.create(this.#node, parseValueBinaryOperationOrExpression(args)),\n    )\n  }\n\n  /**\n   * Change the output type of the expression.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `AndWrapper` with a new output type.\n   */\n  $castTo<C extends SqlBool>(): AndWrapper<DB, TB, C> {\n    return new AndWrapper(this.#node)\n  }\n\n  toOperationNode(): ParensNode {\n    return ParensNode.create(this.#node)\n  }\n}\n"
  },
  {
    "path": "src/expression/expression.ts",
    "content": "import type { AliasNode } from '../operation-node/alias-node.js'\nimport {\n  isOperationNodeSource,\n  type OperationNodeSource,\n} from '../operation-node/operation-node-source.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport { isObject, isString } from '../util/object-utils.js'\n\n/**\n * `Expression` represents an arbitrary SQL expression with a type.\n *\n * Most Kysely methods accept instances of `Expression` and most classes like `SelectQueryBuilder`\n * and the return value of the {@link sql} template tag implement it.\n *\n * ### Examples\n *\n * ```ts\n * import { type Expression, sql } from 'kysely'\n *\n * const exp1: Expression<string> = sql<string>`CONCAT('hello', ' ', 'world')`\n * const exp2: Expression<{ first_name: string }> = db.selectFrom('person').select('first_name')\n * ```\n *\n * You can implement the `Expression` interface to create your own type-safe utilities for Kysely.\n */\nexport interface Expression<T> extends OperationNodeSource {\n  /**\n   * All expressions need to have this getter for complicated type-related reasons.\n   * Simply add this getter for your expression and always return `undefined` from it:\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { type Expression, type OperationNode, sql } from 'kysely'\n   *\n   * class SomeExpression<T> implements Expression<T> {\n   *   get expressionType(): T | undefined {\n   *     return undefined\n   *   }\n   *\n   *   toOperationNode(): OperationNode {\n   *     return sql`some sql here`.toOperationNode()\n   *   }\n   * }\n   * ```\n   *\n   * The getter is needed to make the expression assignable to another expression only\n   * if the types `T` are assignable. Without this property (or some other property\n   * that references `T`), you could assing `Expression<string>` to `Expression<number>`.\n   */\n  get expressionType(): T | undefined\n\n  /**\n   * Creates the OperationNode that describes how to compile this expression into SQL.\n   *\n   * ### Examples\n   *\n   * If you are creating a custom expression, it's often easiest to use the {@link sql}\n   * template tag to build the node:\n   *\n   * ```ts\n   * import { type Expression, type OperationNode, sql } from 'kysely'\n   *\n   * class SomeExpression<T> implements Expression<T> {\n   *   get expressionType(): T | undefined {\n   *     return undefined\n   *   }\n   *\n   *   toOperationNode(): OperationNode {\n   *     return sql`some sql here`.toOperationNode()\n   *   }\n   * }\n   * ```\n   */\n  toOperationNode(): OperationNode\n}\n\n/**\n * An expression with an `as` method.\n */\nexport interface AliasableExpression<T> extends Expression<T> {\n  /**\n   * Returns an aliased version of the expression.\n   *\n   * ### Examples\n   *\n   * In addition to slapping `as \"the_alias\"` at the end of the expression,\n   * this method also provides strict typing:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select((eb) =>\n   *     // `eb.fn<string>` returns an AliasableExpression<string>\n   *     eb.fn<string>('concat', ['first_name', eb.val(' '), 'last_name']).as('full_name')\n   *   )\n   *   .executeTakeFirstOrThrow()\n   *\n   * // `full_name: string` field exists in the result type.\n   * console.log(result.full_name)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   concat(\"first_name\", $1, \"last_name\") as \"full_name\"\n   * from\n   *   \"person\"\n   * ```\n   *\n   * You can also pass in a raw SQL snippet (or any expression) but in that case you must\n   * provide the alias as the only type argument:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const values = sql<{ a: number, b: string }>`(values (1, 'foo'))`\n   *\n   * // The alias is `t(a, b)` which specifies the column names\n   * // in addition to the table name. We must tell kysely that\n   * // columns of the table can be referenced through `t`\n   * // by providing an explicit type argument.\n   * const aliasedValues = values.as<'t'>(sql`t(a, b)`)\n   *\n   * await db\n   *   .insertInto('person')\n   *   .columns(['first_name', 'last_name'])\n   *   .expression(\n   *     db.selectFrom(aliasedValues).select(['t.a', 't.b'])\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"last_name\")\n   * from (values (1, 'foo')) as t(a, b)\n   * select \"t\".\"a\", \"t\".\"b\"\n   * ```\n   */\n  as<A extends string>(alias: A): AliasedExpression<T, A>\n  as<A extends string>(alias: Expression<any>): AliasedExpression<T, A>\n}\n\n/**\n * A type that holds an expression and an alias for it.\n *\n * `AliasedExpression<T, A>` can be used in places where, in addition to the value type `T`, you\n * also need a name `A` for that value. For example anything you can pass into the `select` method\n * needs to implement an `AliasedExpression<T, A>`. `A` becomes the name of the selected expression\n * in the result and `T` becomes its type.\n *\n * ### Examples\n *\n * ```ts\n * import {\n *   AliasNode,\n *   type AliasedExpression,\n *   type Expression,\n *   IdentifierNode\n * } from 'kysely'\n *\n * class SomeAliasedExpression<T, A extends string> implements AliasedExpression<T, A> {\n *   #expression: Expression<T>\n *   #alias: A\n *\n *   constructor(expression: Expression<T>, alias: A) {\n *     this.#expression = expression\n *     this.#alias = alias\n *   }\n *\n *   get expression(): Expression<T> {\n *     return this.#expression\n *   }\n *\n *   get alias(): A {\n *     return this.#alias\n *   }\n *\n *   toOperationNode(): AliasNode {\n *     return AliasNode.create(\n *       this.#expression.toOperationNode(),\n *       IdentifierNode.create(this.#alias)\n *     )\n *   }\n * }\n * ```\n */\nexport interface AliasedExpression<\n  T,\n  A extends string,\n> extends OperationNodeSource {\n  /**\n   * Returns the aliased expression.\n   */\n  get expression(): Expression<T>\n\n  /**\n   * Returns the alias.\n   */\n  get alias(): A | Expression<unknown>\n\n  /**\n   * Creates the OperationNode that describes how to compile this expression into SQL.\n   */\n  toOperationNode(): AliasNode\n}\n\nexport function isExpression(obj: unknown): obj is Expression<any> {\n  return isObject(obj) && 'expressionType' in obj && isOperationNodeSource(obj)\n}\n\nexport function isAliasedExpression(\n  obj: unknown,\n): obj is AliasedExpression<any, any> {\n  return (\n    isObject(obj) &&\n    'expression' in obj &&\n    isString(obj.alias) &&\n    isOperationNodeSource(obj)\n  )\n}\n"
  },
  {
    "path": "src/helpers/mssql.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport type { RawBuilder } from '../raw-builder/raw-builder.js'\nimport { sql } from '../raw-builder/sql.js'\nimport type {\n  ShallowDehydrateObject,\n  ShallowDehydrateValue,\n  Simplify,\n} from '../util/type-utils.js'\n\n/**\n * An MS SQL Server helper for aggregating a subquery into a JSON array.\n *\n * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`.\n * Otherwise the nested selections will be returned as JSON strings.\n *\n * The plugin can be installed like this:\n *\n * ```ts\n * import { Kysely, MssqlDialect, ParseJSONResultsPlugin } from 'kysely'\n * import * as Tarn from 'tarn'\n * import * as Tedious from 'tedious'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new MssqlDialect({\n *     tarn: { options: { max: 10, min: 0 }, ...Tarn },\n *     tedious: {\n *       ...Tedious,\n *       connectionFactory: () => new Tedious.Connection({\n *         authentication: {\n *           options: { password: 'password', userName: 'sa' },\n *           type: 'default',\n *         },\n *         options: { database: 'test', port: 21433, trustServerCertificate: true },\n *         server: 'localhost',\n *       }),\n *     },\n *   }),\n *   plugins: [new ParseJSONResultsPlugin()]\n * })\n * ```\n *\n * ### Examples\n *\n * ```ts\n * import { jsonArrayFrom } from 'kysely/helpers/mssql'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonArrayFrom(\n *       eb.selectFrom('pet')\n *         .select(['pet.id as pet_id', 'pet.name'])\n *         .whereRef('pet.owner_id', '=', 'person.id')\n *         .orderBy('pet.name')\n *         .offset(0)\n *     ).as('pets')\n *   ])\n *   .execute()\n *\n * result[0]?.id\n * result[0]?.pets[0]?.pet_id\n * result[0]?.pets[0]?.name\n * ```\n *\n * The generated SQL (MS SQL Server):\n *\n * ```sql\n * select \"id\", (\n *   select coalesce((select * from (\n *     select \"pet\".\"id\" as \"pet_id\", \"pet\".\"name\"\n *     from \"pet\"\n *     where \"pet\".\"owner_id\" = \"person\".\"id\"\n *     order by \"pet\".\"name\"\n *     offset @1 rows\n *   ) as \"agg\" for json path, include_null_values), '[]')\n * ) as \"pets\"\n * from \"person\"\n * ```\n */\nexport function jsonArrayFrom<O>(\n  expr: Expression<O>,\n): RawBuilder<Simplify<ShallowDehydrateObject<O>>[]> {\n  return sql`coalesce((select * from ${expr} as agg for json path, include_null_values), '[]')`\n}\n\n/**\n * An MS SQL Server helper for turning a subquery into a JSON object.\n *\n * The subquery must only return one row.\n *\n * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`.\n * Otherwise the nested selections will be returned as JSON strings.\n *\n * The plugin can be installed like this:\n *\n * ```ts\n * import { Kysely, MssqlDialect, ParseJSONResultsPlugin } from 'kysely'\n * import * as Tarn from 'tarn'\n * import * as Tedious from 'tedious'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new MssqlDialect({\n *     tarn: { options: { max: 10, min: 0 }, ...Tarn },\n *     tedious: {\n *       ...Tedious,\n *       connectionFactory: () => new Tedious.Connection({\n *         authentication: {\n *           options: { password: 'password', userName: 'sa' },\n *           type: 'default',\n *         },\n *         options: { database: 'test', port: 21433, trustServerCertificate: true },\n *         server: 'localhost',\n *       }),\n *     },\n *   }),\n *   plugins: [new ParseJSONResultsPlugin()]\n * })\n * ```\n *\n * ### Examples\n *\n * ```ts\n * import { jsonObjectFrom } from 'kysely/helpers/mssql'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonObjectFrom(\n *       eb.selectFrom('pet')\n *         .select(['pet.id as pet_id', 'pet.name'])\n *         .whereRef('pet.owner_id', '=', 'person.id')\n *         .where('pet.is_favorite', '=', 1)\n *     ).as('favorite_pet')\n *   ])\n *   .execute()\n *\n * result[0]?.id\n * result[0]?.favorite_pet?.pet_id\n * result[0]?.favorite_pet?.name\n * ```\n *\n * The generated SQL (MS SQL Server):\n *\n * ```sql\n * select \"id\", (\n *   select * from (\n *     select \"pet\".\"id\" as \"pet_id\", \"pet\".\"name\"\n *     from \"pet\"\n *     where \"pet\".\"owner_id\" = \"person\".\"id\"\n *     and \"pet\".\"is_favorite\" = @1\n *   ) as \"agg\" for json path, include_null_values, without_array_wrapper\n * ) as \"favorite_pet\"\n * from \"person\"\n * ```\n */\nexport function jsonObjectFrom<O>(\n  expr: Expression<O>,\n): RawBuilder<Simplify<ShallowDehydrateObject<O>> | null> {\n  return sql`(select * from ${expr} as agg for json path, include_null_values, without_array_wrapper)`\n}\n\n/**\n * The MS SQL Server `json_query` function, single argument variant.\n *\n * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`.\n * Otherwise the nested selections will be returned as JSON strings.\n *\n * The plugin can be installed like this:\n *\n * ```ts\n * import { Kysely, MssqlDialect, ParseJSONResultsPlugin } from 'kysely'\n * import * as Tarn from 'tarn'\n * import * as Tedious from 'tedious'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new MssqlDialect({\n *     tarn: { options: { max: 10, min: 0 }, ...Tarn },\n *     tedious: {\n *       ...Tedious,\n *       connectionFactory: () => new Tedious.Connection({\n *         authentication: {\n *           options: { password: 'password', userName: 'sa' },\n *           type: 'default',\n *         },\n *         options: { database: 'test', port: 21433, trustServerCertificate: true },\n *         server: 'localhost',\n *       }),\n *     },\n *   }),\n *   plugins: [new ParseJSONResultsPlugin()]\n * })\n * ```\n *\n * ### Examples\n *\n * ```ts\n * import { jsonBuildObject } from 'kysely/helpers/mssql'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonBuildObject({\n *       first: eb.ref('first_name'),\n *       last: eb.ref('last_name'),\n *       full: eb.fn('concat', ['first_name', eb.val(' '), 'last_name'])\n *     }).as('name')\n *   ])\n *   .execute()\n * ```\n *\n * The generated SQL (MS SQL Server):\n *\n * ```sql\n * select \"id\", json_query(\n *   '{\"first\":\"'+\"first_name\"+',\"last\":\"'+\"last_name\"+',\"full\":\"'+concat(\"first_name\", ' ', \"last_name\")+'\"}'\n * ) as \"name\"\n * from \"person\"\n * ```\n */\nexport function jsonBuildObject<O extends Record<string, Expression<unknown>>>(\n  obj: O,\n): RawBuilder<\n  Simplify<{\n    [K in keyof O]: O[K] extends Expression<infer V>\n      ? ShallowDehydrateValue<V>\n      : never\n  }>\n> {\n  return sql`json_query('{${sql.join(\n    Object.keys(obj).map((k) => sql`\"${sql.raw(k)}\":\"'+${obj[k]}+'\"`),\n    sql`,`,\n  )}}')`\n}\n"
  },
  {
    "path": "src/helpers/mysql.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport type { SelectQueryNode } from '../operation-node/select-query-node.js'\nimport type { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js'\nimport type { RawBuilder } from '../raw-builder/raw-builder.js'\nimport { sql } from '../raw-builder/sql.js'\nimport { getJsonObjectArgs } from '../util/json-object-args.js'\nimport type {\n  ShallowDehydrateObject,\n  ShallowDehydrateValue,\n  Simplify,\n} from '../util/type-utils.js'\n\n/**\n * A MySQL helper for aggregating a subquery into a JSON array.\n *\n * NOTE: This helper is only guaranteed to fully work with the built-in `MysqlDialect`.\n * While the produced SQL is compatible with all MySQL databases, some third-party dialects\n * may not parse the nested JSON into arrays. In these cases you can use the built in\n * `ParseJSONResultsPlugin` to parse the results.\n *\n * ### Examples\n *\n * ```ts\n * import { jsonArrayFrom } from 'kysely/helpers/mysql'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonArrayFrom(\n *       eb.selectFrom('pet')\n *         .select(['pet.id as pet_id', 'pet.name'])\n *         .whereRef('pet.owner_id', '=', 'person.id')\n *         .orderBy('pet.name')\n *     ).as('pets')\n *   ])\n *   .execute()\n *\n * result[0]?.id\n * result[0]?.pets[0]?.pet_id\n * result[0]?.pets[0]?.name\n * ```\n *\n * The generated SQL (MySQL):\n *\n * ```sql\n * select `id`, (\n *   select cast(coalesce(json_arrayagg(json_object(\n *     'pet_id', `agg`.`pet_id`,\n *     'name', `agg`.`name`\n *   )), '[]') as json) from (\n *     select `pet`.`id` as `pet_id`, `pet`.`name`\n *     from `pet`\n *     where `pet`.`owner_id` = `person`.`id`\n *     order by `pet`.`name`\n *   ) as `agg`\n * ) as `pets`\n * from `person`\n * ```\n */\nexport function jsonArrayFrom<O>(\n  expr: SelectQueryBuilderExpression<O>,\n): RawBuilder<Simplify<ShallowDehydrateObject<O>>[]> {\n  return sql`(select cast(coalesce(json_arrayagg(json_object(${sql.join(\n    getMysqlJsonObjectArgs(expr.toOperationNode(), 'agg'),\n  )})), '[]') as json) from ${expr} as agg)`\n}\n\n/**\n * A MySQL helper for turning a subquery into a JSON object.\n *\n * The subquery must only return one row.\n *\n * NOTE: This helper is only guaranteed to fully work with the built-in `MysqlDialect`.\n * While the produced SQL is compatible with all MySQL databases, some third-party dialects\n * may not parse the nested JSON into objects. In these cases you can use the built in\n * `ParseJSONResultsPlugin` to parse the results.\n *\n * ### Examples\n *\n * ```ts\n * import { jsonObjectFrom } from 'kysely/helpers/mysql'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonObjectFrom(\n *       eb.selectFrom('pet')\n *         .select(['pet.id as pet_id', 'pet.name'])\n *         .whereRef('pet.owner_id', '=', 'person.id')\n *         .where('pet.is_favorite', '=', true)\n *     ).as('favorite_pet')\n *   ])\n *   .execute()\n *\n * result[0]?.id\n * result[0]?.favorite_pet?.pet_id\n * result[0]?.favorite_pet?.name\n * ```\n *\n * The generated SQL (MySQL):\n *\n * ```sql\n * select `id`, (\n *   select json_object(\n *     'pet_id', `obj`.`pet_id`,\n *     'name', `obj`.`name`\n *   ) from (\n *     select `pet`.`id` as `pet_id`, `pet`.`name`\n *     from `pet`\n *     where `pet`.`owner_id` = `person`.`id`\n *     and `pet`.`is_favorite` = ?\n *   ) as obj\n * ) as `favorite_pet`\n * from `person`\n * ```\n */\nexport function jsonObjectFrom<O>(\n  expr: SelectQueryBuilderExpression<O>,\n): RawBuilder<Simplify<ShallowDehydrateObject<O>> | null> {\n  return sql`(select json_object(${sql.join(\n    getMysqlJsonObjectArgs(expr.toOperationNode(), 'obj'),\n  )}) from ${expr} as obj)`\n}\n\n/**\n * The MySQL `json_object` function.\n *\n * NOTE: This helper is only guaranteed to fully work with the built-in `MysqlDialect`.\n * While the produced SQL is compatible with all MySQL databases, some third-party dialects\n * may not parse the nested JSON into objects. In these cases you can use the built in\n * `ParseJSONResultsPlugin` to parse the results.\n *\n * ### Examples\n *\n * ```ts\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonBuildObject({\n *       first: eb.ref('first_name'),\n *       last: eb.ref('last_name'),\n *       full: eb.fn('concat', ['first_name', eb.val(' '), 'last_name'])\n *     }).as('name')\n *   ])\n *   .execute()\n *\n * result[0]?.id\n * result[0]?.name.first\n * result[0]?.name.last\n * result[0]?.name.full\n * ```\n *\n * The generated SQL (MySQL):\n *\n * ```sql\n * select \"id\", json_object(\n *   'first', first_name,\n *   'last', last_name,\n *   'full', concat(`first_name`, ?, `last_name`)\n * ) as \"name\"\n * from \"person\"\n * ```\n */\nexport function jsonBuildObject<O extends Record<string, Expression<unknown>>>(\n  obj: O,\n): RawBuilder<\n  Simplify<{\n    [K in keyof O]: O[K] extends Expression<infer V>\n      ? ShallowDehydrateValue<V>\n      : never\n  }>\n> {\n  return sql`json_object(${sql.join(\n    Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]),\n  )})`\n}\n\nfunction getMysqlJsonObjectArgs(\n  node: SelectQueryNode,\n  table: string,\n): Expression<unknown>[] {\n  try {\n    return getJsonObjectArgs(node, table)\n  } catch {\n    throw new Error(\n      'MySQL jsonArrayFrom and jsonObjectFrom functions can only handle explicit selections due to limitations of the json_object function. selectAll() is not allowed in the subquery.',\n    )\n  }\n}\n"
  },
  {
    "path": "src/helpers/postgres.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport type { RawBuilder } from '../raw-builder/raw-builder.js'\nimport { sql } from '../raw-builder/sql.js'\nimport type {\n  ShallowDehydrateValue,\n  ShallowDehydrateObject,\n  Simplify,\n} from '../util/type-utils.js'\n\n/**\n * A postgres helper for aggregating a subquery (or other expression) into a JSONB array.\n *\n * ### Examples\n *\n * <!-- siteExample(\"select\", \"Nested array\", 110) -->\n *\n * While kysely is not an ORM and it doesn't have the concept of relations, we do provide\n * helpers for fetching nested objects and arrays in a single query. In this example we\n * use the `jsonArrayFrom` helper to fetch person's pets along with the person's id.\n *\n * Please keep in mind that the helpers under the `kysely/helpers` folder, including\n * `jsonArrayFrom`, are not guaranteed to work with third party dialects. In order for\n * them to work, the dialect must automatically parse the `json` data type into\n * JavaScript JSON values like objects and arrays. Some dialects might simply return\n * the data as a JSON string. In these cases you can use the built in `ParseJSONResultsPlugin`\n * to parse the results.\n *\n * ```ts\n * import { jsonArrayFrom } from 'kysely/helpers/postgres'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonArrayFrom(\n *       eb.selectFrom('pet')\n *         .select(['pet.id as pet_id', 'pet.name'])\n *         .whereRef('pet.owner_id', '=', 'person.id')\n *         .orderBy('pet.name')\n *     ).as('pets')\n *   ])\n *   .execute()\n * ```\n *\n * The generated SQL (PostgreSQL):\n *\n * ```sql\n * select \"id\", (\n *   select coalesce(json_agg(agg), '[]') from (\n *     select \"pet\".\"id\" as \"pet_id\", \"pet\".\"name\"\n *     from \"pet\"\n *     where \"pet\".\"owner_id\" = \"person\".\"id\"\n *     order by \"pet\".\"name\"\n *   ) as agg\n * ) as \"pets\"\n * from \"person\"\n * ```\n */\nexport function jsonArrayFrom<O>(\n  expr: Expression<O>,\n): RawBuilder<Simplify<ShallowDehydrateObject<O>>[]> {\n  return sql`(select coalesce(json_agg(agg), '[]') from ${expr} as agg)`\n}\n\n/**\n * A postgres helper for turning a subquery (or other expression) into a JSON object.\n *\n * The subquery must only return one row.\n *\n * ### Examples\n *\n * <!-- siteExample(\"select\", \"Nested object\", 120) -->\n *\n * While kysely is not an ORM and it doesn't have the concept of relations, we do provide\n * helpers for fetching nested objects and arrays in a single query. In this example we\n * use the `jsonObjectFrom` helper to fetch person's favorite pet along with the person's id.\n *\n * Please keep in mind that the helpers under the `kysely/helpers` folder, including\n * `jsonObjectFrom`, are not guaranteed to work with third-party dialects. In order for\n * them to work, the dialect must automatically parse the `json` data type into\n * JavaScript JSON values like objects and arrays. Some dialects might simply return\n * the data as a JSON string. In these cases you can use the built in `ParseJSONResultsPlugin`\n * to parse the results.\n *\n * ```ts\n * import { jsonObjectFrom } from 'kysely/helpers/postgres'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonObjectFrom(\n *       eb.selectFrom('pet')\n *         .select(['pet.id as pet_id', 'pet.name'])\n *         .whereRef('pet.owner_id', '=', 'person.id')\n *         .where('pet.is_favorite', '=', true)\n *     ).as('favorite_pet')\n *   ])\n *   .execute()\n * ```\n *\n * The generated SQL (PostgreSQL):\n *\n * ```sql\n * select \"id\", (\n *   select to_json(obj) from (\n *     select \"pet\".\"id\" as \"pet_id\", \"pet\".\"name\"\n *     from \"pet\"\n *     where \"pet\".\"owner_id\" = \"person\".\"id\"\n *     and \"pet\".\"is_favorite\" = $1\n *   ) as obj\n * ) as \"favorite_pet\"\n * from \"person\"\n * ```\n */\nexport function jsonObjectFrom<O>(\n  expr: Expression<O>,\n): RawBuilder<Simplify<ShallowDehydrateObject<O>> | null> {\n  return sql`(select to_json(obj) from ${expr} as obj)`\n}\n\n/**\n * The PostgreSQL `json_build_object` function.\n *\n * NOTE: This helper is only guaranteed to fully work with the built-in `PostgresDialect`.\n * While the produced SQL is compatible with all PostgreSQL databases, some third-party dialects\n * may not parse the nested JSON into objects. In these cases you can use the built in\n * `ParseJSONResultsPlugin` to parse the results.\n *\n * ### Examples\n *\n * ```ts\n * import { sql } from 'kysely'\n * import { jsonBuildObject } from 'kysely/helpers/postgres'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonBuildObject({\n *       first: eb.ref('first_name'),\n *       last: eb.ref('last_name'),\n *       full: sql<string>`first_name || ' ' || last_name`\n *     }).as('name')\n *   ])\n *   .execute()\n *\n * result[0]?.id\n * result[0]?.name.first\n * result[0]?.name.last\n * result[0]?.name.full\n * ```\n *\n * The generated SQL (PostgreSQL):\n *\n * ```sql\n * select \"id\", json_build_object(\n *   'first', first_name,\n *   'last', last_name,\n *   'full', first_name || ' ' || last_name\n * ) as \"name\"\n * from \"person\"\n * ```\n */\nexport function jsonBuildObject<O extends Record<string, Expression<unknown>>>(\n  obj: O,\n): RawBuilder<\n  Simplify<{\n    [K in keyof O]: O[K] extends Expression<infer V>\n      ? ShallowDehydrateValue<V>\n      : never\n  }>\n> {\n  return sql`json_build_object(${sql.join(\n    Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]),\n  )})`\n}\n\nexport type MergeAction = 'INSERT' | 'UPDATE' | 'DELETE'\n\n/**\n * The PostgreSQL `merge_action` function.\n *\n * This function can be used in a `returning` clause to get the action that was\n * performed in a `mergeInto` query. The function returns one of the following\n * strings: `'INSERT'`, `'UPDATE'`, or `'DELETE'`.\n *\n * ### Examples\n *\n * ```ts\n * import { mergeAction } from 'kysely/helpers/postgres'\n *\n * const result = await db\n *   .mergeInto('person as p')\n *   .using('person_backup as pb', 'p.id', 'pb.id')\n *   .whenMatched()\n *   .thenUpdateSet(({ ref }) => ({\n *     first_name: ref('pb.first_name'),\n *     updated_at: ref('pb.updated_at').$castTo<string | null>(),\n *   }))\n *   .whenNotMatched()\n *   .thenInsertValues(({ ref}) => ({\n *     id: ref('pb.id'),\n *     first_name: ref('pb.first_name'),\n *     created_at: ref('pb.updated_at'),\n *     updated_at: ref('pb.updated_at').$castTo<string | null>(),\n *   }))\n *   .returning([mergeAction().as('action'), 'p.id', 'p.updated_at'])\n *   .execute()\n *\n * result[0].action\n * ```\n *\n * The generated SQL (PostgreSQL):\n *\n * ```sql\n * merge into \"person\" as \"p\"\n * using \"person_backup\" as \"pb\" on \"p\".\"id\" = \"pb\".\"id\"\n * when matched then update set\n *   \"first_name\" = \"pb\".\"first_name\",\n *   \"updated_at\" = \"pb\".\"updated_at\"::text\n * when not matched then insert values (\"id\", \"first_name\", \"created_at\", \"updated_at\")\n * values (\"pb\".\"id\", \"pb\".\"first_name\", \"pb\".\"updated_at\", \"pb\".\"updated_at\")\n * returning merge_action() as \"action\", \"p\".\"id\", \"p\".\"updated_at\"\n * ```\n */\nexport function mergeAction(): RawBuilder<MergeAction> {\n  return sql`merge_action()`\n}\n"
  },
  {
    "path": "src/helpers/sqlite.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport type { SelectQueryNode } from '../operation-node/select-query-node.js'\nimport type { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js'\nimport type { RawBuilder } from '../raw-builder/raw-builder.js'\nimport { sql } from '../raw-builder/sql.js'\nimport { getJsonObjectArgs } from '../util/json-object-args.js'\nimport type {\n  ShallowDehydrateObject,\n  ShallowDehydrateValue,\n  Simplify,\n} from '../util/type-utils.js'\n\n/**\n * A SQLite helper for aggregating a subquery into a JSON array.\n *\n * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`.\n * Otherwise the nested selections will be returned as JSON strings.\n *\n * The plugin can be installed like this:\n *\n * ```ts\n * import * as Sqlite from 'better-sqlite3'\n * import { Kysely, ParseJSONResultsPlugin, SqliteDialect } from 'kysely'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new SqliteDialect({\n *     database: new Sqlite(':memory:')\n *   }),\n *   plugins: [new ParseJSONResultsPlugin()]\n * })\n * ```\n *\n * ### Examples\n *\n * ```ts\n * import { jsonArrayFrom } from 'kysely/helpers/sqlite'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonArrayFrom(\n *       eb.selectFrom('pet')\n *         .select(['pet.id as pet_id', 'pet.name'])\n *         .whereRef('pet.owner_id', '=', 'person.id')\n *         .orderBy('pet.name')\n *     ).as('pets')\n *   ])\n *   .execute()\n *\n * result[0]?.id\n * result[0]?.pets[0].pet_id\n * result[0]?.pets[0].name\n * ```\n *\n * The generated SQL (SQLite):\n *\n * ```sql\n * select \"id\", (\n *   select coalesce(json_group_array(json_object(\n *     'pet_id', \"agg\".\"pet_id\",\n *     'name', \"agg\".\"name\"\n *   )), '[]') from (\n *     select \"pet\".\"id\" as \"pet_id\", \"pet\".\"name\"\n *     from \"pet\"\n *     where \"pet\".\"owner_id\" = \"person\".\"id\"\n *     order by \"pet\".\"name\"\n *   ) as \"agg\"\n * ) as \"pets\"\n * from \"person\"\n * ```\n */\nexport function jsonArrayFrom<O>(\n  expr: SelectQueryBuilderExpression<O>,\n): RawBuilder<Simplify<ShallowDehydrateObject<O>>[]> {\n  return sql`(select coalesce(json_group_array(json_object(${sql.join(\n    getSqliteJsonObjectArgs(expr.toOperationNode(), 'agg'),\n  )})), '[]') from ${expr} as agg)`\n}\n\n/**\n * A SQLite helper for turning a subquery into a JSON object.\n *\n * The subquery must only return one row.\n *\n * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`.\n * Otherwise the nested selections will be returned as JSON strings.\n *\n * The plugin can be installed like this:\n *\n * ```ts\n * import * as Sqlite from 'better-sqlite3'\n * import { Kysely, ParseJSONResultsPlugin, SqliteDialect } from 'kysely'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new SqliteDialect({\n *     database: new Sqlite(':memory:')\n *   }),\n *   plugins: [new ParseJSONResultsPlugin()]\n * })\n * ```\n *\n * ### Examples\n *\n * ```ts\n * import { jsonObjectFrom } from 'kysely/helpers/sqlite'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonObjectFrom(\n *       eb.selectFrom('pet')\n *         .select(['pet.id as pet_id', 'pet.name'])\n *         .whereRef('pet.owner_id', '=', 'person.id')\n *         .where('pet.is_favorite', '=', true)\n *     ).as('favorite_pet')\n *   ])\n *   .execute()\n *\n * result[0]?.id\n * result[0]?.favorite_pet?.pet_id\n * result[0]?.favorite_pet?.name\n * ```\n *\n * The generated SQL (SQLite):\n *\n * ```sql\n * select \"id\", (\n *   select json_object(\n *     'pet_id', \"obj\".\"pet_id\",\n *     'name', \"obj\".\"name\"\n *   ) from (\n *     select \"pet\".\"id\" as \"pet_id\", \"pet\".\"name\"\n *     from \"pet\"\n *     where \"pet\".\"owner_id\" = \"person\".\"id\"\n *     and \"pet\".\"is_favorite\" = ?\n *   ) as obj\n * ) as \"favorite_pet\"\n * from \"person\";\n * ```\n */\nexport function jsonObjectFrom<O>(\n  expr: SelectQueryBuilderExpression<O>,\n): RawBuilder<Simplify<ShallowDehydrateObject<O>> | null> {\n  return sql`(select json_object(${sql.join(\n    getSqliteJsonObjectArgs(expr.toOperationNode(), 'obj'),\n  )}) from ${expr} as obj)`\n}\n\n/**\n * The SQLite `json_object` function.\n *\n * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`.\n * Otherwise the nested selections will be returned as JSON strings.\n *\n * The plugin can be installed like this:\n *\n * ```ts\n * import * as Sqlite from 'better-sqlite3'\n * import { Kysely, ParseJSONResultsPlugin, SqliteDialect } from 'kysely'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new SqliteDialect({\n *     database: new Sqlite(':memory:')\n *   }),\n *   plugins: [new ParseJSONResultsPlugin()]\n * })\n * ```\n *\n * ### Examples\n *\n * ```ts\n * import { sql } from 'kysely'\n * import { jsonBuildObject } from 'kysely/helpers/sqlite'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     jsonBuildObject({\n *       first: eb.ref('first_name'),\n *       last: eb.ref('last_name'),\n *       full: sql<string>`first_name || ' ' || last_name`\n *     }).as('name')\n *   ])\n *   .execute()\n *\n * result[0]?.id\n * result[0]?.name.first\n * result[0]?.name.last\n * result[0]?.name.full\n * ```\n *\n * The generated SQL (SQLite):\n *\n * ```sql\n * select \"id\", json_object(\n *   'first', first_name,\n *   'last', last_name,\n *   'full', \"first_name\" || ' ' || \"last_name\"\n * ) as \"name\"\n * from \"person\"\n * ```\n */\nexport function jsonBuildObject<O extends Record<string, Expression<unknown>>>(\n  obj: O,\n): RawBuilder<\n  Simplify<{\n    [K in keyof O]: O[K] extends Expression<infer V>\n      ? ShallowDehydrateValue<V>\n      : never\n  }>\n> {\n  return sql`json_object(${sql.join(\n    Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]),\n  )})`\n}\n\nfunction getSqliteJsonObjectArgs(\n  node: SelectQueryNode,\n  table: string,\n): Expression<unknown>[] {\n  try {\n    return getJsonObjectArgs(node, table)\n  } catch {\n    throw new Error(\n      'SQLite jsonArrayFrom and jsonObjectFrom functions can only handle explicit selections due to limitations of the json_object function. selectAll() is not allowed in the subquery.',\n    )\n  }\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "export * from './kysely.js'\nexport * from './query-creator.js'\n\nexport * from './expression/expression.js'\nexport {\n  type ExpressionBuilder,\n  expressionBuilder,\n} from './expression/expression-builder.js'\nexport * from './expression/expression-wrapper.js'\n\nexport * from './query-builder/where-interface.js'\nexport * from './query-builder/returning-interface.js'\nexport * from './query-builder/output-interface.js'\nexport * from './query-builder/having-interface.js'\nexport * from './query-builder/order-by-interface.js'\nexport * from './query-builder/select-query-builder.js'\nexport * from './query-builder/insert-query-builder.js'\nexport * from './query-builder/update-query-builder.js'\nexport * from './query-builder/delete-query-builder.js'\nexport * from './query-builder/no-result-error.js'\nexport * from './query-builder/join-builder.js'\nexport * from './query-builder/function-module.js'\nexport * from './query-builder/insert-result.js'\nexport * from './query-builder/delete-result.js'\nexport * from './query-builder/update-result.js'\nexport * from './query-builder/on-conflict-builder.js'\nexport * from './query-builder/aggregate-function-builder.js'\nexport * from './query-builder/case-builder.js'\nexport * from './query-builder/json-path-builder.js'\nexport * from './query-builder/merge-query-builder.js'\nexport * from './query-builder/merge-result.js'\nexport * from './query-builder/order-by-item-builder.js'\n\nexport * from './raw-builder/raw-builder.js'\nexport * from './raw-builder/sql.js'\n\nexport * from './query-executor/query-executor.js'\nexport * from './query-executor/default-query-executor.js'\nexport * from './query-executor/noop-query-executor.js'\nexport * from './query-executor/query-executor-provider.js'\n\nexport * from './query-compiler/default-query-compiler.js'\nexport * from './query-compiler/compiled-query.js'\n\nexport * from './schema/schema.js'\nexport * from './schema/create-table-builder.js'\nexport * from './schema/create-type-builder.js'\nexport * from './schema/drop-table-builder.js'\nexport * from './schema/drop-type-builder.js'\nexport * from './schema/create-index-builder.js'\nexport * from './schema/drop-index-builder.js'\nexport * from './schema/create-schema-builder.js'\nexport * from './schema/drop-schema-builder.js'\nexport * from './schema/column-definition-builder.js'\nexport * from './schema/foreign-key-constraint-builder.js'\nexport * from './schema/alter-table-builder.js'\nexport * from './schema/create-view-builder.js'\nexport * from './schema/refresh-materialized-view-builder.js'\nexport * from './schema/drop-view-builder.js'\nexport * from './schema/alter-column-builder.js'\n\nexport * from './dynamic/dynamic.js'\nexport * from './dynamic/dynamic-reference-builder.js'\nexport * from './dynamic/dynamic-table-builder.js'\n\nexport * from './driver/driver.js'\nexport * from './driver/database-connection.js'\nexport * from './driver/connection-provider.js'\nexport * from './driver/default-connection-provider.js'\nexport * from './driver/single-connection-provider.js'\nexport * from './driver/dummy-driver.js'\n\nexport * from './dialect/dialect.js'\nexport * from './dialect/dialect-adapter.js'\nexport * from './dialect/dialect-adapter-base.js'\nexport * from './dialect/database-introspector.js'\n\nexport * from './dialect/sqlite/sqlite-dialect.js'\nexport * from './dialect/sqlite/sqlite-dialect-config.js'\nexport * from './dialect/sqlite/sqlite-driver.js'\nexport * from './dialect/postgres/postgres-query-compiler.js'\nexport * from './dialect/postgres/postgres-introspector.js'\nexport * from './dialect/postgres/postgres-adapter.js'\n\nexport * from './dialect/mysql/mysql-dialect.js'\nexport * from './dialect/mysql/mysql-dialect-config.js'\nexport * from './dialect/mysql/mysql-driver.js'\nexport * from './dialect/mysql/mysql-query-compiler.js'\nexport * from './dialect/mysql/mysql-introspector.js'\nexport * from './dialect/mysql/mysql-adapter.js'\n\nexport * from './dialect/postgres/postgres-driver.js'\nexport * from './dialect/postgres/postgres-dialect-config.js'\nexport * from './dialect/postgres/postgres-dialect.js'\nexport * from './dialect/sqlite/sqlite-query-compiler.js'\nexport * from './dialect/sqlite/sqlite-introspector.js'\nexport * from './dialect/sqlite/sqlite-adapter.js'\n\nexport * from './dialect/mssql/mssql-adapter.js'\nexport * from './dialect/mssql/mssql-dialect-config.js'\nexport * from './dialect/mssql/mssql-dialect.js'\nexport * from './dialect/mssql/mssql-driver.js'\nexport * from './dialect/mssql/mssql-introspector.js'\nexport * from './dialect/mssql/mssql-query-compiler.js'\n\nexport * from './query-compiler/default-query-compiler.js'\nexport * from './query-compiler/query-compiler.js'\n\nexport * from './migration/migrator.js'\nexport * from './migration/file-migration-provider.js'\n\nexport * from './plugin/kysely-plugin.js'\nexport * from './plugin/camel-case/camel-case-plugin.js'\nexport * from './plugin/deduplicate-joins/deduplicate-joins-plugin.js'\nexport * from './plugin/with-schema/with-schema-plugin.js'\nexport * from './plugin/parse-json-results/parse-json-results-plugin.js'\nexport * from './plugin/handle-empty-in-lists/handle-empty-in-lists-plugin.js'\nexport * from './plugin/handle-empty-in-lists/handle-empty-in-lists.js'\n\nexport * from './operation-node/add-column-node.js'\nexport * from './operation-node/add-constraint-node.js'\nexport * from './operation-node/add-index-node.js'\nexport * from './operation-node/aggregate-function-node.js'\nexport * from './operation-node/alias-node.js'\nexport * from './operation-node/alter-column-node.js'\nexport * from './operation-node/alter-table-node.js'\nexport * from './operation-node/and-node.js'\nexport * from './operation-node/binary-operation-node.js'\nexport * from './operation-node/case-node.js'\nexport * from './operation-node/cast-node.js'\nexport * from './operation-node/check-constraint-node.js'\nexport * from './operation-node/collate-node.js'\nexport * from './operation-node/column-definition-node.js'\nexport * from './operation-node/column-node.js'\nexport * from './operation-node/column-update-node.js'\nexport * from './operation-node/common-table-expression-name-node.js'\nexport * from './operation-node/common-table-expression-node.js'\nexport * from './operation-node/constraint-node.js'\nexport * from './operation-node/create-index-node.js'\nexport * from './operation-node/create-schema-node.js'\nexport * from './operation-node/create-table-node.js'\nexport * from './operation-node/create-type-node.js'\nexport * from './operation-node/create-view-node.js'\nexport * from './operation-node/refresh-materialized-view-node.js'\nexport * from './operation-node/data-type-node.js'\nexport * from './operation-node/default-insert-value-node.js'\nexport * from './operation-node/default-value-node.js'\nexport * from './operation-node/delete-query-node.js'\nexport * from './operation-node/drop-column-node.js'\nexport * from './operation-node/drop-constraint-node.js'\nexport * from './operation-node/drop-index-node.js'\nexport * from './operation-node/drop-schema-node.js'\nexport * from './operation-node/drop-table-node.js'\nexport * from './operation-node/drop-type-node.js'\nexport * from './operation-node/drop-view-node.js'\nexport * from './operation-node/explain-node.js'\nexport * from './operation-node/fetch-node.js'\nexport * from './operation-node/foreign-key-constraint-node.js'\nexport * from './operation-node/from-node.js'\nexport * from './operation-node/function-node.js'\nexport * from './operation-node/generated-node.js'\nexport * from './operation-node/group-by-item-node.js'\nexport * from './operation-node/group-by-node.js'\nexport * from './operation-node/having-node.js'\nexport * from './operation-node/identifier-node.js'\nexport * from './operation-node/insert-query-node.js'\nexport * from './operation-node/join-node.js'\nexport * from './operation-node/json-operator-chain-node.js'\nexport * from './operation-node/json-path-leg-node.js'\nexport * from './operation-node/json-path-node.js'\nexport * from './operation-node/json-reference-node.js'\nexport * from './operation-node/limit-node.js'\nexport * from './operation-node/list-node.js'\nexport * from './operation-node/matched-node.js'\nexport * from './operation-node/merge-query-node.js'\nexport * from './operation-node/modify-column-node.js'\nexport * from './operation-node/offset-node.js'\nexport * from './operation-node/on-conflict-node.js'\nexport * from './operation-node/on-duplicate-key-node.js'\nexport * from './operation-node/on-node.js'\nexport * from './operation-node/operation-node-source.js'\nexport * from './operation-node/operation-node-transformer.js'\nexport * from './operation-node/operation-node-visitor.js'\nexport * from './operation-node/operation-node.js'\nexport * from './operation-node/operator-node.js'\nexport * from './operation-node/or-action-node.js'\nexport * from './operation-node/or-node.js'\nexport * from './operation-node/order-by-item-node.js'\nexport * from './operation-node/order-by-node.js'\nexport * from './operation-node/output-node.js'\nexport * from './operation-node/over-node.js'\nexport * from './operation-node/parens-node.js'\nexport * from './operation-node/partition-by-item-node.js'\nexport * from './operation-node/partition-by-node.js'\nexport * from './operation-node/primary-key-constraint-node.js'\nexport * from './operation-node/primitive-value-list-node.js'\nexport * from './operation-node/query-node.js'\nexport * from './operation-node/raw-node.js'\nexport * from './operation-node/reference-node.js'\nexport * from './operation-node/references-node.js'\nexport * from './operation-node/rename-column-node.js'\nexport * from './operation-node/rename-constraint-node.js'\nexport * from './operation-node/returning-node.js'\nexport * from './operation-node/schemable-identifier-node.js'\nexport * from './operation-node/select-all-node.js'\nexport * from './operation-node/select-modifier-node.js'\nexport * from './operation-node/select-query-node.js'\nexport * from './operation-node/selection-node.js'\nexport * from './operation-node/set-operation-node.js'\nexport * from './operation-node/simple-reference-expression-node.js'\nexport * from './operation-node/table-node.js'\nexport * from './operation-node/top-node.js'\nexport * from './operation-node/tuple-node.js'\nexport * from './operation-node/unary-operation-node.js'\nexport * from './operation-node/unique-constraint-node.js'\nexport * from './operation-node/update-query-node.js'\nexport * from './operation-node/using-node.js'\nexport * from './operation-node/value-list-node.js'\nexport * from './operation-node/value-node.js'\nexport * from './operation-node/values-node.js'\nexport * from './operation-node/when-node.js'\nexport * from './operation-node/where-node.js'\nexport * from './operation-node/with-node.js'\n\nexport * from './util/column-type.js'\nexport * from './util/compilable.js'\nexport * from './util/explainable.js'\nexport * from './util/streamable.js'\nexport * from './util/log.js'\nexport type {\n  AnyAliasedColumn,\n  AnyAliasedColumnWithTable,\n  AnyColumn,\n  AnyColumnWithTable,\n  DrainOuterGeneric,\n  Equals,\n  ExtractColumnType,\n  UnknownRow,\n  Simplify,\n  SqlBool,\n  Nullable,\n  NumbersWhenDataTypeNotAvailable,\n  NotNull,\n  NumericString,\n  ShallowDehydrateObject,\n  ShallowDehydrateValue,\n  SimplifyResult,\n  SimplifySingleResult,\n  StringsWhenDataTypeNotAvailable,\n} from './util/type-utils.js'\nexport * from './util/infer-result.js'\nexport { logOnce } from './util/log-once.js'\nexport { createQueryId, type QueryId } from './util/query-id.js'\nexport type { KyselyTypeError } from './util/type-error.js'\n\nexport type {\n  SelectExpression,\n  SelectCallback,\n  SelectArg,\n  Selection,\n  CallbackSelection,\n} from './parser/select-parser.js'\nexport type {\n  ReferenceExpression,\n  ReferenceExpressionOrList,\n  SimpleReferenceExpression,\n  StringReference,\n  ExtractTypeFromStringReference,\n  ExtractTypeFromReferenceExpression,\n} from './parser/reference-parser.js'\nexport type {\n  ValueExpression,\n  ValueExpressionOrList,\n} from './parser/value-parser.js'\nexport type {\n  SimpleTableReference,\n  TableExpression,\n  TableExpressionOrList,\n} from './parser/table-parser.js'\nexport type {\n  JoinReferenceExpression,\n  JoinCallbackExpression,\n} from './parser/join-parser.js'\nexport type { InsertObject } from './parser/insert-values-parser.js'\nexport type { UpdateObject } from './parser/update-set-parser.js'\nexport type {\n  OrderByExpression,\n  OrderByDirectionExpression,\n  OrderByModifiers,\n  OrderByDirection,\n  OrderByModifiersCallbackExpression,\n} from './parser/order-by-parser.js'\nexport type {\n  ComparisonOperatorExpression,\n  OperandValueExpression,\n  OperandValueExpressionOrList,\n  FilterObject,\n} from './parser/binary-operation-parser.js'\nexport type { ExistsExpression } from './parser/unary-operation-parser.js'\nexport type {\n  OperandExpression,\n  ExpressionOrFactory,\n} from './parser/expression-parser.js'\nexport type { Collation } from './parser/collate-parser.js'\nexport type { QueryCreatorWithCommonTableExpression } from './parser/with-parser.js'\n"
  },
  {
    "path": "src/kysely.ts",
    "content": "import type { Dialect } from './dialect/dialect.js'\nimport { SchemaModule } from './schema/schema.js'\nimport { DynamicModule } from './dynamic/dynamic.js'\nimport { DefaultConnectionProvider } from './driver/default-connection-provider.js'\nimport type { QueryExecutor } from './query-executor/query-executor.js'\nimport { QueryCreator, type QueryCreatorProps } from './query-creator.js'\nimport type { KyselyPlugin } from './plugin/kysely-plugin.js'\nimport { DefaultQueryExecutor } from './query-executor/default-query-executor.js'\nimport type { DatabaseIntrospector } from './dialect/database-introspector.js'\nimport { freeze, isObject, isUndefined } from './util/object-utils.js'\nimport { RuntimeDriver } from './driver/runtime-driver.js'\nimport { SingleConnectionProvider } from './driver/single-connection-provider.js'\nimport {\n  type Driver,\n  type IsolationLevel,\n  type AccessMode,\n  validateTransactionSettings,\n} from './driver/driver.js'\nimport {\n  createFunctionModule,\n  type FunctionModule,\n} from './query-builder/function-module.js'\nimport { Log, type LogConfig } from './util/log.js'\nimport type { QueryExecutorProvider } from './query-executor/query-executor-provider.js'\nimport type {\n  DatabaseConnection,\n  QueryResult,\n} from './driver/database-connection.js'\nimport type { CompiledQuery } from './query-compiler/compiled-query.js'\nimport { createQueryId, type QueryId } from './util/query-id.js'\nimport { type Compilable, isCompilable } from './util/compilable.js'\nimport { CaseBuilder } from './query-builder/case-builder.js'\nimport { CaseNode } from './operation-node/case-node.js'\nimport { parseExpression } from './parser/expression-parser.js'\nimport type { Expression } from './expression/expression.js'\nimport { WithSchemaPlugin } from './plugin/with-schema/with-schema-plugin.js'\nimport type { DrainOuterGeneric } from './util/type-utils.js'\nimport type {\n  QueryCompiler,\n  RootOperationNode,\n} from './query-compiler/query-compiler.js'\nimport type {\n  ReleaseSavepoint,\n  RollbackToSavepoint,\n} from './parser/savepoint-parser.js'\nimport {\n  type ControlledConnection,\n  provideControlledConnection,\n} from './util/provide-controlled-connection.js'\nimport type { ConnectionProvider } from './driver/connection-provider.js'\nimport { logOnce } from './util/log-once.js'\n\ndeclare global {\n  interface AsyncDisposable {}\n  interface SymbolConstructor {\n    readonly asyncDispose: unique symbol\n  }\n}\n\n// @ts-ignore\nSymbol.asyncDispose ??= Symbol('Symbol.asyncDispose')\n\n/**\n * The main Kysely class.\n *\n * You should create one instance of `Kysely` per database using the {@link Kysely}\n * constructor. Each `Kysely` instance maintains its own connection pool.\n *\n * ### Examples\n *\n * This example assumes your database has a \"person\" table:\n *\n * ```ts\n * import * as Sqlite from 'better-sqlite3'\n * import { type Generated, Kysely, SqliteDialect } from 'kysely'\n *\n * interface Database {\n *   person: {\n *     id: Generated<number>\n *     first_name: string\n *     last_name: string | null\n *   }\n * }\n *\n * const db = new Kysely<Database>({\n *   dialect: new SqliteDialect({\n *     database: new Sqlite(':memory:'),\n *   })\n * })\n * ```\n *\n * @typeParam DB - The database interface type. Keys of this type must be table names\n *    in the database and values must be interfaces that describe the rows in those\n *    tables. See the examples above.\n */\nexport class Kysely<DB>\n  extends QueryCreator<DB>\n  implements QueryExecutorProvider, AsyncDisposable\n{\n  readonly #props: KyselyProps\n\n  constructor(args: KyselyConfig)\n  constructor(args: KyselyProps)\n  constructor(args: KyselyConfig | KyselyProps) {\n    let superProps: QueryCreatorProps\n    let props: KyselyProps\n\n    if (isKyselyProps(args)) {\n      superProps = { executor: args.executor }\n      props = { ...args }\n    } else {\n      const dialect = args.dialect\n\n      const driver = dialect.createDriver()\n      const compiler = dialect.createQueryCompiler()\n      const adapter = dialect.createAdapter()\n\n      const log = new Log(args.log ?? [])\n      const runtimeDriver = new RuntimeDriver(driver, log)\n\n      const connectionProvider = new DefaultConnectionProvider(runtimeDriver)\n      const executor = new DefaultQueryExecutor(\n        compiler,\n        adapter,\n        connectionProvider,\n        args.plugins ?? [],\n      )\n\n      superProps = { executor }\n      props = {\n        config: args,\n        executor,\n        dialect,\n        driver: runtimeDriver,\n      }\n    }\n\n    super(superProps)\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Returns the {@link SchemaModule} module for building database schema.\n   */\n  get schema(): SchemaModule {\n    return new SchemaModule(this.#props.executor)\n  }\n\n  /**\n   * Returns a the {@link DynamicModule} module.\n   *\n   * The {@link DynamicModule} module can be used to bypass strict typing and\n   * passing in dynamic values for the queries.\n   */\n  get dynamic(): DynamicModule<DB> {\n    return new DynamicModule<DB>()\n  }\n\n  /**\n   * Returns a {@link DatabaseIntrospector | database introspector}.\n   */\n  get introspection(): DatabaseIntrospector {\n    return this.#props.dialect.createIntrospector(this.withoutPlugins())\n  }\n\n  /**\n   * Creates a `case` statement/operator.\n   *\n   * See {@link ExpressionBuilder.case} for more information.\n   */\n  case(): CaseBuilder<DB, keyof DB>\n\n  case<V>(value: Expression<V>): CaseBuilder<DB, keyof DB, V>\n\n  case<V>(value?: Expression<V>): any {\n    return new CaseBuilder({\n      node: CaseNode.create(\n        isUndefined(value) ? undefined : parseExpression(value),\n      ),\n    })\n  }\n\n  /**\n   * Returns a {@link FunctionModule} that can be used to write somewhat type-safe function\n   * calls.\n   *\n   * ```ts\n   * const { count } = db.fn\n   *\n   * await db.selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .select([\n   *     'id',\n   *     count('pet.id').as('person_count'),\n   *   ])\n   *   .groupBy('person.id')\n   *   .having(count('pet.id'), '>', 10)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"id\", count(\"pet\".\"id\") as \"person_count\"\n   * from \"person\"\n   * inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * group by \"person\".\"id\"\n   * having count(\"pet\".\"id\") > $1\n   * ```\n   *\n   * Why \"somewhat\" type-safe? Because the function calls are not bound to the\n   * current query context. They allow you to reference columns and tables that\n   * are not in the current query. E.g. remove the `innerJoin` from the previous\n   * query and TypeScript won't even complain.\n   *\n   * If you want to make the function calls fully type-safe, you can use the\n   * {@link ExpressionBuilder.fn} getter for a query context-aware, stricter {@link FunctionModule}.\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .select((eb) => [\n   *     'person.id',\n   *     eb.fn.count('pet.id').as('pet_count')\n   *   ])\n   *   .groupBy('person.id')\n   *   .having((eb) => eb.fn.count('pet.id'), '>', 10)\n   *   .execute()\n   * ```\n   */\n  get fn(): FunctionModule<DB, keyof DB> {\n    return createFunctionModule()\n  }\n\n  /**\n   * Creates a {@link TransactionBuilder} that can be used to run queries inside a transaction.\n   *\n   * The returned {@link TransactionBuilder} can be used to configure the transaction. The\n   * {@link TransactionBuilder.execute} method can then be called to run the transaction.\n   * {@link TransactionBuilder.execute} takes a function that is run inside the\n   * transaction. If the function throws an exception,\n   * 1. the exception is caught,\n   * 2. the transaction is rolled back, and\n   * 3. the exception is thrown again.\n   * Otherwise the transaction is committed.\n   *\n   * The callback function passed to the {@link TransactionBuilder.execute | execute}\n   * method gets the transaction object as its only argument. The transaction is\n   * of type {@link Transaction} which inherits {@link Kysely}. Any query\n   * started through the transaction object is executed inside the transaction.\n   *\n   * To run a controlled transaction, allowing you to commit and rollback manually,\n   * use {@link startTransaction} instead.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"transactions\", \"Simple transaction\", 10) -->\n   *\n   * This example inserts two rows in a transaction. If an exception is thrown inside\n   * the callback passed to the `execute` method,\n   * 1. the exception is caught,\n   * 2. the transaction is rolled back, and\n   * 3. the exception is thrown again.\n   * Otherwise the transaction is committed.\n   *\n   * ```ts\n   * const catto = await db.transaction().execute(async (trx) => {\n   *   const jennifer = await trx.insertInto('person')\n   *     .values({\n   *       first_name: 'Jennifer',\n   *       last_name: 'Aniston',\n   *       age: 40,\n   *     })\n   *     .returning('id')\n   *     .executeTakeFirstOrThrow()\n   *\n   *   return await trx.insertInto('pet')\n   *     .values({\n   *       owner_id: jennifer.id,\n   *       name: 'Catto',\n   *       species: 'cat',\n   *       is_favorite: false,\n   *     })\n   *     .returningAll()\n   *     .executeTakeFirst()\n   * })\n   * ```\n   *\n   * Setting the isolation level:\n   *\n   * ```ts\n   * import type { Kysely } from 'kysely'\n   *\n   * await db\n   *   .transaction()\n   *   .setIsolationLevel('serializable')\n   *   .execute(async (trx) => {\n   *     await doStuff(trx)\n   *   })\n   *\n   * async function doStuff(kysely: typeof db) {\n   *   // ...\n   * }\n   * ```\n   */\n  transaction(): TransactionBuilder<DB> {\n    return new TransactionBuilder({ ...this.#props })\n  }\n\n  /**\n   * Creates a {@link ControlledTransactionBuilder} that can be used to run queries inside a controlled transaction.\n   *\n   * The returned {@link ControlledTransactionBuilder} can be used to configure the transaction.\n   * The {@link ControlledTransactionBuilder.execute} method can then be called\n   * to start the transaction and return a {@link ControlledTransaction}.\n   *\n   * A {@link ControlledTransaction} allows you to commit and rollback manually,\n   * execute savepoint commands. It extends {@link Transaction} which extends {@link Kysely},\n   * so you can run queries inside the transaction. Once the transaction is committed,\n   * or rolled back, it can't be used anymore - all queries will throw an error.\n   * This is to prevent accidentally running queries outside the transaction - where\n   * atomicity is not guaranteed anymore.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"transactions\", \"Controlled transaction\", 11) -->\n   *\n   * A controlled transaction allows you to commit and rollback manually, execute\n   * savepoint commands, and queries in general.\n   *\n   * In this example we start a transaction, use it to insert two rows and then commit\n   * the transaction. If an error is thrown, we catch it and rollback the transaction.\n   *\n   * ```ts\n   * const trx = await db.startTransaction().execute()\n   *\n   * try {\n   *   const jennifer = await trx.insertInto('person')\n   *     .values({\n   *       first_name: 'Jennifer',\n   *       last_name: 'Aniston',\n   *       age: 40,\n   *     })\n   *     .returning('id')\n   *     .executeTakeFirstOrThrow()\n   *\n   *   const catto = await trx.insertInto('pet')\n   *     .values({\n   *       owner_id: jennifer.id,\n   *       name: 'Catto',\n   *       species: 'cat',\n   *       is_favorite: false,\n   *     })\n   *     .returningAll()\n   *     .executeTakeFirstOrThrow()\n   *\n   *   await trx.commit().execute()\n   *\n   *   // ...\n   * } catch (error) {\n   *   await trx.rollback().execute()\n   * }\n   * ```\n   *\n   * <!-- siteExample(\"transactions\", \"Controlled transaction /w savepoints\", 12) -->\n   *\n   * A controlled transaction allows you to commit and rollback manually, execute\n   * savepoint commands, and queries in general.\n   *\n   * In this example we start a transaction, insert a person, create a savepoint,\n   * try inserting a toy and a pet, and if an error is thrown, we rollback to the\n   * savepoint. Eventually we release the savepoint, insert an audit record and\n   * commit the transaction. If an error is thrown, we catch it and rollback the\n   * transaction.\n   *\n   * ```ts\n   * const trx = await db.startTransaction().execute()\n   *\n   * try {\n   *   const jennifer = await trx\n   *     .insertInto('person')\n   *     .values({\n   *       first_name: 'Jennifer',\n   *       last_name: 'Aniston',\n   *       age: 40,\n   *     })\n   *     .returning('id')\n   *     .executeTakeFirstOrThrow()\n   *\n   *   const trxAfterJennifer = await trx.savepoint('after_jennifer').execute()\n   *\n   *   try {\n   *     const catto = await trxAfterJennifer\n   *       .insertInto('pet')\n   *       .values({\n   *         owner_id: jennifer.id,\n   *         name: 'Catto',\n   *         species: 'cat',\n   *       })\n   *       .returning('id')\n   *       .executeTakeFirstOrThrow()\n   *\n   *     await trxAfterJennifer\n   *       .insertInto('toy')\n   *       .values({ name: 'Bone', price: 1.99, pet_id: catto.id })\n   *       .execute()\n   *   } catch (error) {\n   *     await trxAfterJennifer.rollbackToSavepoint('after_jennifer').execute()\n   *   }\n   *\n   *   await trxAfterJennifer.releaseSavepoint('after_jennifer').execute()\n   *\n   *   await trx.insertInto('audit').values({ action: 'added Jennifer' }).execute()\n   *\n   *   await trx.commit().execute()\n   * } catch (error) {\n   *   await trx.rollback().execute()\n   * }\n   * ```\n   */\n  startTransaction(): ControlledTransactionBuilder<DB> {\n    return new ControlledTransactionBuilder({ ...this.#props })\n  }\n\n  /**\n   * Provides a kysely instance bound to a single database connection.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db\n   *   .connection()\n   *   .execute(async (db) => {\n   *     // `db` is an instance of `Kysely` that's bound to a single\n   *     // database connection. All queries executed through `db` use\n   *     // the same connection.\n   *     await doStuff(db)\n   *   })\n   *\n   * async function doStuff(kysely: typeof db) {\n   *   // ...\n   * }\n   * ```\n   */\n  connection(): ConnectionBuilder<DB> {\n    return new ConnectionBuilder({ ...this.#props })\n  }\n\n  /**\n   * Returns a copy of this Kysely instance with the given plugin installed.\n   */\n  override withPlugin(plugin: KyselyPlugin): Kysely<DB> {\n    return new Kysely({\n      ...this.#props,\n      executor: this.#props.executor.withPlugin(plugin),\n    })\n  }\n\n  /**\n   * Returns a copy of this Kysely instance without any plugins.\n   */\n  override withoutPlugins(): Kysely<DB> {\n    return new Kysely({\n      ...this.#props,\n      executor: this.#props.executor.withoutPlugins(),\n    })\n  }\n\n  /**\n   * @override\n   */\n  override withSchema(schema: string): Kysely<DB> {\n    return new Kysely({\n      ...this.#props,\n      executor: this.#props.executor.withPluginAtFront(\n        new WithSchemaPlugin(schema),\n      ),\n    })\n  }\n\n  /**\n   * Returns a copy of this Kysely instance with tables added to its\n   * database type.\n   *\n   * This method only modifies the types and doesn't affect any of the\n   * executed queries in any way.\n   *\n   * ### Examples\n   *\n   * The following example adds and uses a temporary table:\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('temp_table')\n   *   .temporary()\n   *   .addColumn('some_column', 'integer')\n   *   .execute()\n   *\n   * const tempDb = db.withTables<{\n   *   temp_table: {\n   *     some_column: number\n   *   }\n   * }>()\n   *\n   * await tempDb\n   *   .insertInto('temp_table')\n   *   .values({ some_column: 100 })\n   *   .execute()\n   * ```\n   */\n  withTables<T extends Record<string, Record<string, any>>>(): Kysely<\n    DrainOuterGeneric<DB & T>\n  > {\n    return new Kysely({ ...this.#props })\n  }\n\n  /**\n   * Releases all resources and disconnects from the database.\n   *\n   * You need to call this when you are done using the `Kysely` instance.\n   */\n  async destroy(): Promise<void> {\n    await this.#props.driver.destroy()\n  }\n\n  /**\n   * Returns true if this `Kysely` instance is a transaction.\n   *\n   * You can also use `db instanceof Transaction`.\n   */\n  get isTransaction(): boolean {\n    return false\n  }\n\n  /**\n   * @internal\n   * @private\n   */\n  getExecutor(): QueryExecutor {\n    return this.#props.executor\n  }\n\n  /**\n   * Executes a given compiled query or query builder.\n   *\n   * See {@link https://github.com/kysely-org/kysely/blob/master/site/docs/recipes/0004-splitting-query-building-and-execution.md#execute-compiled-queries splitting build, compile and execute code recipe} for more information.\n   */\n  executeQuery<R>(\n    query: CompiledQuery<R> | Compilable<R>,\n    // TODO: remove this in the future. deprecated in  0.28.x\n    queryId?: QueryId,\n  ): Promise<QueryResult<R>> {\n    if (queryId !== undefined) {\n      logOnce(\n        'Passing `queryId` in `db.executeQuery` is deprecated and will result in a compile-time error in the future.',\n      )\n    }\n\n    const compiledQuery = isCompilable(query) ? query.compile() : query\n\n    return this.getExecutor().executeQuery<R>(compiledQuery)\n  }\n\n  async [Symbol.asyncDispose]() {\n    await this.destroy()\n  }\n}\n\nexport class Transaction<DB> extends Kysely<DB> {\n  readonly #props: KyselyProps\n\n  constructor(props: KyselyProps) {\n    super(props)\n    this.#props = props\n  }\n\n  // The return type is `true` instead of `boolean` to make Kysely<DB>\n  // unassignable to Transaction<DB> while allowing assignment the\n  // other way around.\n  override get isTransaction(): true {\n    return true\n  }\n\n  override transaction(): TransactionBuilder<DB> {\n    throw new Error(\n      'calling the transaction method for a Transaction is not supported',\n    )\n  }\n\n  override connection(): ConnectionBuilder<DB> {\n    throw new Error(\n      'calling the connection method for a Transaction is not supported',\n    )\n  }\n\n  override async destroy(): Promise<void> {\n    throw new Error(\n      'calling the destroy method for a Transaction is not supported',\n    )\n  }\n\n  override withPlugin(plugin: KyselyPlugin): Transaction<DB> {\n    return new Transaction({\n      ...this.#props,\n      executor: this.#props.executor.withPlugin(plugin),\n    })\n  }\n\n  override withoutPlugins(): Transaction<DB> {\n    return new Transaction({\n      ...this.#props,\n      executor: this.#props.executor.withoutPlugins(),\n    })\n  }\n\n  override withSchema(schema: string): Transaction<DB> {\n    return new Transaction({\n      ...this.#props,\n      executor: this.#props.executor.withPluginAtFront(\n        new WithSchemaPlugin(schema),\n      ),\n    })\n  }\n\n  override withTables<\n    T extends Record<string, Record<string, any>>,\n  >(): Transaction<DrainOuterGeneric<DB & T>> {\n    return new Transaction({ ...this.#props })\n  }\n}\n\nexport interface KyselyProps {\n  readonly config: KyselyConfig\n  readonly driver: Driver\n  readonly executor: QueryExecutor\n  readonly dialect: Dialect\n}\n\nexport function isKyselyProps(obj: unknown): obj is KyselyProps {\n  return (\n    isObject(obj) &&\n    isObject(obj.config) &&\n    isObject(obj.driver) &&\n    isObject(obj.executor) &&\n    isObject(obj.dialect)\n  )\n}\n\nexport interface KyselyConfig {\n  readonly dialect: Dialect\n  readonly plugins?: KyselyPlugin[]\n\n  /**\n   * A list of log levels to log or a custom logger function.\n   *\n   * Currently there's only two levels: `query` and `error`.\n   * This will be expanded based on user feedback later.\n   *\n   * ### Examples\n   *\n   * Setting up built-in logging for preferred log levels:\n   *\n   * ```ts\n   * import * as Sqlite from 'better-sqlite3'\n   * import { Kysely, SqliteDialect } from 'kysely'\n   * import type { Database } from 'type-editor' // imaginary module\n   *\n   * const db = new Kysely<Database>({\n   *   dialect: new SqliteDialect({\n   *     database: new Sqlite(':memory:'),\n   *   }),\n   *   log: ['query', 'error']\n   * })\n   * ```\n   *\n   * Setting up custom logging:\n   *\n   * ```ts\n   * import * as Sqlite from 'better-sqlite3'\n   * import { Kysely, SqliteDialect } from 'kysely'\n   * import type { Database } from 'type-editor' // imaginary module\n   *\n   * const db = new Kysely<Database>({\n   *   dialect: new SqliteDialect({\n   *     database: new Sqlite(':memory:'),\n   *   }),\n   *   log(event): void {\n   *     if (event.level === 'query') {\n   *       console.log(event.query.sql)\n   *       console.log(event.query.parameters)\n   *     }\n   *   }\n   * })\n   * ```\n   */\n  readonly log?: LogConfig\n}\n\nexport class ConnectionBuilder<DB> {\n  readonly #props: ConnectionBuilderProps\n\n  constructor(props: ConnectionBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  async execute<T>(callback: (db: Kysely<DB>) => Promise<T>): Promise<T> {\n    return this.#props.executor.provideConnection(async (connection) => {\n      const executor = this.#props.executor.withConnectionProvider(\n        new SingleConnectionProvider(connection),\n      )\n\n      const db = new Kysely<DB>({\n        ...this.#props,\n        executor,\n      })\n\n      return await callback(db)\n    })\n  }\n}\n\ninterface ConnectionBuilderProps extends KyselyProps {}\n\nexport class TransactionBuilder<DB> {\n  readonly #props: TransactionBuilderProps\n\n  constructor(props: TransactionBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  setAccessMode(accessMode: AccessMode): TransactionBuilder<DB> {\n    return new TransactionBuilder({\n      ...this.#props,\n      accessMode,\n    })\n  }\n\n  setIsolationLevel(isolationLevel: IsolationLevel): TransactionBuilder<DB> {\n    return new TransactionBuilder({\n      ...this.#props,\n      isolationLevel,\n    })\n  }\n\n  async execute<T>(callback: (trx: Transaction<DB>) => Promise<T>): Promise<T> {\n    const { isolationLevel, accessMode, ...kyselyProps } = this.#props\n    const settings = { isolationLevel, accessMode }\n\n    validateTransactionSettings(settings)\n\n    return this.#props.executor.provideConnection(async (connection) => {\n      const state = { isCommitted: false, isRolledBack: false }\n\n      const executor = new NotCommittedOrRolledBackAssertingExecutor(\n        this.#props.executor.withConnectionProvider(\n          new SingleConnectionProvider(connection),\n        ),\n        state,\n      )\n\n      const transaction = new Transaction<DB>({\n        ...kyselyProps,\n        executor,\n      })\n\n      let transactionBegun = false\n      try {\n        await this.#props.driver.beginTransaction(connection, settings)\n        transactionBegun = true\n\n        const result = await callback(transaction)\n\n        await this.#props.driver.commitTransaction(connection)\n        state.isCommitted = true\n\n        return result\n      } catch (error) {\n        if (transactionBegun) {\n          await this.#props.driver.rollbackTransaction(connection)\n          state.isRolledBack = true\n        }\n\n        throw error\n      }\n    })\n  }\n}\n\ninterface TransactionBuilderProps extends KyselyProps {\n  readonly accessMode?: AccessMode\n  readonly isolationLevel?: IsolationLevel\n}\n\nexport class ControlledTransactionBuilder<DB> {\n  readonly #props: TransactionBuilderProps\n\n  constructor(props: TransactionBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  setAccessMode(accessMode: AccessMode): ControlledTransactionBuilder<DB> {\n    return new ControlledTransactionBuilder({\n      ...this.#props,\n      accessMode,\n    })\n  }\n\n  setIsolationLevel(\n    isolationLevel: IsolationLevel,\n  ): ControlledTransactionBuilder<DB> {\n    return new ControlledTransactionBuilder({\n      ...this.#props,\n      isolationLevel,\n    })\n  }\n\n  async execute(): Promise<ControlledTransaction<DB>> {\n    const { isolationLevel, accessMode, ...props } = this.#props\n    const settings = { isolationLevel, accessMode }\n\n    validateTransactionSettings(settings)\n\n    const connection = await provideControlledConnection(this.#props.executor)\n\n    await this.#props.driver.beginTransaction(connection.connection, settings)\n\n    return new ControlledTransaction({\n      ...props,\n      connection,\n      executor: this.#props.executor.withConnectionProvider(\n        new SingleConnectionProvider(connection.connection),\n      ),\n    })\n  }\n}\n\nexport class ControlledTransaction<\n  DB,\n  S extends string[] = [],\n> extends Transaction<DB> {\n  readonly #props: ControlledTransactionProps\n  readonly #compileQuery: QueryCompiler['compileQuery']\n  readonly #state: ControlledTransctionState\n\n  constructor(props: ControlledTransactionProps) {\n    const state = { isCommitted: false, isRolledBack: false }\n    props = {\n      ...props,\n      executor: new NotCommittedOrRolledBackAssertingExecutor(\n        props.executor,\n        state,\n      ),\n    }\n    const { connection, ...transactionProps } = props\n    super(transactionProps)\n\n    this.#props = freeze(props)\n    this.#state = state\n\n    const queryId = createQueryId()\n    this.#compileQuery = (node) => props.executor.compileQuery(node, queryId)\n  }\n\n  get isCommitted(): boolean {\n    return this.#state.isCommitted\n  }\n\n  get isRolledBack(): boolean {\n    return this.#state.isRolledBack\n  }\n\n  /**\n   * Commits the transaction.\n   *\n   * See {@link rollback}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { Kysely } from 'kysely'\n   * import type { Database } from 'type-editor' // imaginary module\n   *\n   * const trx = await db.startTransaction().execute()\n   *\n   * try {\n   *   await doSomething(trx)\n   *\n   *   await trx.commit().execute()\n   * } catch (error) {\n   *   await trx.rollback().execute()\n   * }\n   *\n   * async function doSomething(kysely: Kysely<Database>) {}\n   * ```\n   */\n  commit(): Command<void> {\n    assertNotCommittedOrRolledBack(this.#state)\n\n    return new Command(async () => {\n      await this.#props.driver.commitTransaction(\n        this.#props.connection.connection,\n      )\n      this.#state.isCommitted = true\n      this.#props.connection.release()\n    })\n  }\n\n  /**\n   * Rolls back the transaction.\n   *\n   * See {@link commit} and {@link rollbackToSavepoint}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { Kysely } from 'kysely'\n   * import type { Database } from 'type-editor' // imaginary module\n   *\n   * const trx = await db.startTransaction().execute()\n   *\n   * try {\n   *   await doSomething(trx)\n   *\n   *   await trx.commit().execute()\n   * } catch (error) {\n   *   await trx.rollback().execute()\n   * }\n   *\n   * async function doSomething(kysely: Kysely<Database>) {}\n   * ```\n   */\n  rollback(): Command<void> {\n    assertNotCommittedOrRolledBack(this.#state)\n\n    return new Command(async () => {\n      await this.#props.driver.rollbackTransaction(\n        this.#props.connection.connection,\n      )\n      this.#state.isRolledBack = true\n      this.#props.connection.release()\n    })\n  }\n\n  /**\n   * Creates a savepoint with a given name.\n   *\n   * See {@link rollbackToSavepoint} and {@link releaseSavepoint}.\n   *\n   * For a type-safe experience, you should use the returned instance from now on.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { Kysely } from 'kysely'\n   * import type { Database } from 'type-editor' // imaginary module\n   *\n   * const trx = await db.startTransaction().execute()\n   *\n   * await insertJennifer(trx)\n   *\n   * const trxAfterJennifer = await trx.savepoint('after_jennifer').execute()\n   *\n   * try {\n   *   await doSomething(trxAfterJennifer)\n   * } catch (error) {\n   *   await trxAfterJennifer.rollbackToSavepoint('after_jennifer').execute()\n   * }\n   *\n   * async function insertJennifer(kysely: Kysely<Database>) {}\n   * async function doSomething(kysely: Kysely<Database>) {}\n   * ```\n   */\n  savepoint<SN extends string>(\n    savepointName: SN extends S ? never : SN,\n  ): Command<ControlledTransaction<DB, [...S, SN]>> {\n    assertNotCommittedOrRolledBack(this.#state)\n\n    return new Command(async () => {\n      await this.#props.driver.savepoint?.(\n        this.#props.connection.connection,\n        savepointName,\n        this.#compileQuery,\n      )\n\n      return new ControlledTransaction({ ...this.#props })\n    })\n  }\n\n  /**\n   * Rolls back to a savepoint with a given name.\n   *\n   * See {@link savepoint} and {@link releaseSavepoint}.\n   *\n   * You must use the same instance returned by {@link savepoint}, or\n   * escape the type-check by using `as any`.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { Kysely } from 'kysely'\n   * import type { Database } from 'type-editor' // imaginary module\n   *\n   * const trx = await db.startTransaction().execute()\n   *\n   * await insertJennifer(trx)\n   *\n   * const trxAfterJennifer = await trx.savepoint('after_jennifer').execute()\n   *\n   * try {\n   *   await doSomething(trxAfterJennifer)\n   * } catch (error) {\n   *   await trxAfterJennifer.rollbackToSavepoint('after_jennifer').execute()\n   * }\n   *\n   * async function insertJennifer(kysely: Kysely<Database>) {}\n   * async function doSomething(kysely: Kysely<Database>) {}\n   * ```\n   */\n  rollbackToSavepoint<SN extends S[number]>(\n    savepointName: SN,\n  ): RollbackToSavepoint<S, SN> extends string[]\n    ? Command<ControlledTransaction<DB, RollbackToSavepoint<S, SN>>>\n    : never {\n    assertNotCommittedOrRolledBack(this.#state)\n\n    return new Command(async () => {\n      await this.#props.driver.rollbackToSavepoint?.(\n        this.#props.connection.connection,\n        savepointName,\n        this.#compileQuery,\n      )\n\n      return new ControlledTransaction({ ...this.#props })\n    }) as any\n  }\n\n  /**\n   * Releases a savepoint with a given name.\n   *\n   * See {@link savepoint} and {@link rollbackToSavepoint}.\n   *\n   * You must use the same instance returned by {@link savepoint}, or\n   * escape the type-check by using `as any`.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { Kysely } from 'kysely'\n   * import type { Database } from 'type-editor' // imaginary module\n   *\n   * const trx = await db.startTransaction().execute()\n   *\n   * await insertJennifer(trx)\n   *\n   * const trxAfterJennifer = await trx.savepoint('after_jennifer').execute()\n   *\n   * try {\n   *   await doSomething(trxAfterJennifer)\n   * } catch (error) {\n   *   await trxAfterJennifer.rollbackToSavepoint('after_jennifer').execute()\n   * }\n   *\n   * await trxAfterJennifer.releaseSavepoint('after_jennifer').execute()\n   *\n   * await doSomethingElse(trx)\n   *\n   * async function insertJennifer(kysely: Kysely<Database>) {}\n   * async function doSomething(kysely: Kysely<Database>) {}\n   * async function doSomethingElse(kysely: Kysely<Database>) {}\n   * ```\n   */\n  releaseSavepoint<SN extends S[number]>(\n    savepointName: SN,\n  ): ReleaseSavepoint<S, SN> extends string[]\n    ? Command<ControlledTransaction<DB, ReleaseSavepoint<S, SN>>>\n    : never {\n    assertNotCommittedOrRolledBack(this.#state)\n\n    return new Command(async () => {\n      await this.#props.driver.releaseSavepoint?.(\n        this.#props.connection.connection,\n        savepointName,\n        this.#compileQuery,\n      )\n\n      return new ControlledTransaction({ ...this.#props })\n    }) as any\n  }\n\n  override withPlugin(plugin: KyselyPlugin): ControlledTransaction<DB, S> {\n    return new ControlledTransaction({\n      ...this.#props,\n      executor: this.#props.executor.withPlugin(plugin),\n    })\n  }\n\n  override withoutPlugins(): ControlledTransaction<DB, S> {\n    return new ControlledTransaction({\n      ...this.#props,\n      executor: this.#props.executor.withoutPlugins(),\n    })\n  }\n\n  override withSchema(schema: string): ControlledTransaction<DB, S> {\n    return new ControlledTransaction({\n      ...this.#props,\n      executor: this.#props.executor.withPluginAtFront(\n        new WithSchemaPlugin(schema),\n      ),\n    })\n  }\n\n  override withTables<\n    T extends Record<string, Record<string, any>>,\n  >(): ControlledTransaction<DrainOuterGeneric<DB & T>, S> {\n    return new ControlledTransaction({ ...this.#props })\n  }\n}\n\ninterface ControlledTransctionState {\n  isCommitted: boolean\n  isRolledBack: boolean\n}\n\ninterface ControlledTransactionProps extends KyselyProps {\n  readonly connection: ControlledConnection\n}\n\nexport class Command<T> {\n  readonly #cb: () => Promise<T>\n\n  constructor(cb: () => Promise<T>) {\n    this.#cb = cb\n  }\n\n  /**\n   * Executes the command.\n   */\n  async execute(): Promise<T> {\n    return await this.#cb()\n  }\n}\n\nfunction assertNotCommittedOrRolledBack(\n  state: ControlledTransctionState,\n): void {\n  if (state.isCommitted) {\n    throw new Error('Transaction is already committed')\n  }\n\n  if (state.isRolledBack) {\n    throw new Error('Transaction is already rolled back')\n  }\n}\n\n/**\n * An executor wrapper that asserts that the transaction state is not committed\n * or rolled back when a query is executed.\n *\n * @internal\n */\nclass NotCommittedOrRolledBackAssertingExecutor implements QueryExecutor {\n  readonly #executor: QueryExecutor\n  readonly #state: ControlledTransctionState\n\n  constructor(executor: QueryExecutor, state: ControlledTransctionState) {\n    if (executor instanceof NotCommittedOrRolledBackAssertingExecutor) {\n      this.#executor = executor.#executor\n    } else {\n      this.#executor = executor\n    }\n\n    this.#state = state\n  }\n\n  get adapter() {\n    return this.#executor.adapter\n  }\n\n  get plugins() {\n    return this.#executor.plugins\n  }\n\n  transformQuery<T extends RootOperationNode>(node: T, queryId: QueryId): T {\n    return this.#executor.transformQuery(node, queryId)\n  }\n\n  compileQuery<R = unknown>(\n    node: RootOperationNode,\n    queryId: QueryId,\n  ): CompiledQuery<R> {\n    return this.#executor.compileQuery(node, queryId)\n  }\n\n  provideConnection<T>(\n    consumer: (connection: DatabaseConnection) => Promise<T>,\n  ): Promise<T> {\n    return this.#executor.provideConnection(consumer)\n  }\n\n  executeQuery<R>(compiledQuery: CompiledQuery<R>): Promise<QueryResult<R>> {\n    assertNotCommittedOrRolledBack(this.#state)\n    return this.#executor.executeQuery(compiledQuery)\n  }\n\n  stream<R>(\n    compiledQuery: CompiledQuery<R>,\n    chunkSize: number,\n  ): AsyncIterableIterator<QueryResult<R>> {\n    assertNotCommittedOrRolledBack(this.#state)\n    return this.#executor.stream(compiledQuery, chunkSize)\n  }\n\n  withConnectionProvider(\n    connectionProvider: ConnectionProvider,\n  ): QueryExecutor {\n    return new NotCommittedOrRolledBackAssertingExecutor(\n      this.#executor.withConnectionProvider(connectionProvider),\n      this.#state,\n    )\n  }\n\n  withPlugin(plugin: KyselyPlugin): QueryExecutor {\n    return new NotCommittedOrRolledBackAssertingExecutor(\n      this.#executor.withPlugin(plugin),\n      this.#state,\n    )\n  }\n\n  withPlugins(plugins: ReadonlyArray<KyselyPlugin>): QueryExecutor {\n    return new NotCommittedOrRolledBackAssertingExecutor(\n      this.#executor.withPlugins(plugins),\n      this.#state,\n    )\n  }\n\n  withPluginAtFront(plugin: KyselyPlugin): QueryExecutor {\n    return new NotCommittedOrRolledBackAssertingExecutor(\n      this.#executor.withPluginAtFront(plugin),\n      this.#state,\n    )\n  }\n\n  withoutPlugins(): QueryExecutor {\n    return new NotCommittedOrRolledBackAssertingExecutor(\n      this.#executor.withoutPlugins(),\n      this.#state,\n    )\n  }\n}\n"
  },
  {
    "path": "src/migration/file-migration-provider.ts",
    "content": "import { isFunction, isObject } from '../util/object-utils.js'\nimport type { Migration, MigrationProvider } from './migrator.js'\n\n/**\n * Reads all migrations from a folder in node.js.\n *\n * ### Examples\n *\n * ```ts\n * import { promises as fs } from 'node:fs'\n * import path from 'node:path'\n *\n * new FileMigrationProvider({\n *   fs,\n *   path,\n *   migrationFolder: 'path/to/migrations/folder'\n * })\n * ```\n */\nexport class FileMigrationProvider implements MigrationProvider {\n  readonly #props: FileMigrationProviderProps\n\n  constructor(props: FileMigrationProviderProps) {\n    this.#props = props\n  }\n\n  async getMigrations(): Promise<Record<string, Migration>> {\n    const migrations: Record<string, Migration> = {}\n    const files = await this.#props.fs.readdir(this.#props.migrationFolder)\n\n    for (const fileName of files) {\n      if (\n        fileName.endsWith('.js') ||\n        (fileName.endsWith('.ts') && !fileName.endsWith('.d.ts')) ||\n        fileName.endsWith('.mjs') ||\n        (fileName.endsWith('.mts') && !fileName.endsWith('.d.mts'))\n      ) {\n        const migration = await import(\n          /* webpackIgnore: true */ this.#props.path.join(\n            this.#props.migrationFolder,\n            fileName,\n          )\n        )\n        const migrationKey = fileName.substring(0, fileName.lastIndexOf('.'))\n\n        // Handle esModuleInterop export's `default` prop...\n        if (isMigration(migration?.default)) {\n          migrations[migrationKey] = migration.default\n        } else if (isMigration(migration)) {\n          migrations[migrationKey] = migration\n        }\n      }\n    }\n\n    return migrations\n  }\n}\n\nfunction isMigration(obj: unknown): obj is Migration {\n  return isObject(obj) && isFunction(obj.up)\n}\n\nexport interface FileMigrationProviderFS {\n  readdir(path: string): Promise<string[]>\n}\n\nexport interface FileMigrationProviderPath {\n  join(...path: string[]): string\n}\n\nexport interface FileMigrationProviderProps {\n  fs: FileMigrationProviderFS\n  path: FileMigrationProviderPath\n  migrationFolder: string\n}\n"
  },
  {
    "path": "src/migration/migrator.ts",
    "content": "import type { MigrationLockOptions } from '../dialect/dialect-adapter.js'\nimport type { Kysely } from '../kysely.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport { NoopPlugin } from '../plugin/noop-plugin.js'\nimport { WithSchemaPlugin } from '../plugin/with-schema/with-schema-plugin.js'\nimport type { CreateSchemaBuilder } from '../schema/create-schema-builder.js'\nimport type { CreateTableBuilder } from '../schema/create-table-builder.js'\nimport { freeze, getLast, isObject } from '../util/object-utils.js'\n\nexport const DEFAULT_MIGRATION_TABLE = 'kysely_migration'\nexport const DEFAULT_MIGRATION_LOCK_TABLE = 'kysely_migration_lock'\nexport const DEFAULT_ALLOW_UNORDERED_MIGRATIONS = false\nexport const MIGRATION_LOCK_ID = 'migration_lock'\nexport const NO_MIGRATIONS: NoMigrations = freeze({ __noMigrations__: true })\n\nexport interface Migration {\n  up(db: Kysely<any>): Promise<void>\n\n  /**\n   * An optional down method.\n   *\n   * If you don't provide a down method, the migration is skipped when\n   * migrating down.\n   */\n  down?(db: Kysely<any>): Promise<void>\n}\n\n/**\n * A class for running migrations.\n *\n * ### Example\n *\n * This example uses the {@link FileMigrationProvider} that reads migrations\n * files from a single folder. You can easily implement your own\n * {@link MigrationProvider} if you want to provide migrations some\n * other way.\n *\n * ```ts\n * import { promises as fs } from 'node:fs'\n * import path from 'node:path'\n * import * as Sqlite from 'better-sqlite3'\n * import {\n *   FileMigrationProvider,\n *   Kysely,\n *   Migrator,\n *   SqliteDialect\n * } from 'kysely'\n *\n * const db = new Kysely<any>({\n *   dialect: new SqliteDialect({\n *     database: Sqlite(':memory:')\n *   })\n * })\n *\n * const migrator = new Migrator({\n *   db,\n *   provider: new FileMigrationProvider({\n *     fs,\n *     // Path to the folder that contains all your migrations.\n *     migrationFolder: 'some/path/to/migrations',\n *     path,\n *   })\n * })\n * ```\n */\nexport class Migrator {\n  readonly #props: MigratorProps\n\n  constructor(props: MigratorProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Returns a {@link MigrationInfo} object for each migration.\n   *\n   * The returned array is sorted by migration name.\n   */\n  async getMigrations(): Promise<ReadonlyArray<MigrationInfo>> {\n    const tableExists = await this.#doesTableExist(this.#migrationTable)\n\n    const executedMigrations = tableExists\n      ? await this.#props.db\n          .withPlugin(this.#schemaPlugin)\n          .selectFrom(this.#migrationTable)\n          .select(['name', 'timestamp'])\n          .$narrowType<{ name: string; timestamp: string }>()\n          .execute()\n      : []\n\n    const migrations = await this.#resolveMigrations()\n\n    return migrations.map(({ name, ...migration }) => {\n      const executed = executedMigrations.find((it) => it.name === name)\n\n      return {\n        name,\n        migration,\n        executedAt: executed ? new Date(executed.timestamp) : undefined,\n      }\n    })\n  }\n\n  /**\n   * Runs all migrations that have not yet been run.\n   *\n   * This method returns a {@link MigrationResultSet} instance and _never_ throws.\n   * {@link MigrationResultSet.error} holds the error if something went wrong.\n   * {@link MigrationResultSet.results} contains information about which migrations\n   * were executed and which failed. See the examples below.\n   *\n   * This method goes through all possible migrations provided by the provider and runs the\n   * ones whose names come alphabetically after the last migration that has been run. If the\n   * list of executed migrations doesn't match the beginning of the list of possible migrations\n   * an error is returned.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { promises as fs } from 'node:fs'\n   * import path from 'node:path'\n   * import * as Sqlite from 'better-sqlite3'\n   * import { FileMigrationProvider, Migrator } from 'kysely'\n   *\n   * const migrator = new Migrator({\n   *   db,\n   *   provider: new FileMigrationProvider({\n   *     fs,\n   *     migrationFolder: 'some/path/to/migrations',\n   *     path,\n   *   })\n   * })\n   *\n   * const { error, results } = await migrator.migrateToLatest()\n   *\n   * results?.forEach((it) => {\n   *   if (it.status === 'Success') {\n   *     console.log(`migration \"${it.migrationName}\" was executed successfully`)\n   *   } else if (it.status === 'Error') {\n   *     console.error(`failed to execute migration \"${it.migrationName}\"`)\n   *   }\n   * })\n   *\n   * if (error) {\n   *   console.error('failed to run `migrateToLatest`')\n   *   console.error(error)\n   * }\n   * ```\n   */\n  async migrateToLatest(): Promise<MigrationResultSet> {\n    return this.#migrate(() => ({ direction: 'Up', step: Infinity }))\n  }\n\n  /**\n   * Migrate up/down to a specific migration.\n   *\n   * This method returns a {@link MigrationResultSet} instance and _never_ throws.\n   * {@link MigrationResultSet.error} holds the error if something went wrong.\n   * {@link MigrationResultSet.results} contains information about which migrations\n   * were executed and which failed.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { promises as fs } from 'node:fs'\n   * import path from 'node:path'\n   * import { FileMigrationProvider, Migrator } from 'kysely'\n   *\n   * const migrator = new Migrator({\n   *   db,\n   *   provider: new FileMigrationProvider({\n   *     fs,\n   *     // Path to the folder that contains all your migrations.\n   *     migrationFolder: 'some/path/to/migrations',\n   *     path,\n   *   })\n   * })\n   *\n   * await migrator.migrateTo('some_migration')\n   * ```\n   *\n   * If you specify the name of the first migration, this method migrates\n   * down to the first migration, but doesn't run the `down` method of\n   * the first migration. In case you want to migrate all the way down,\n   * you can use a special constant `NO_MIGRATIONS`:\n   *\n   * ```ts\n   * import { promises as fs } from 'node:fs'\n   * import path from 'node:path'\n   * import { FileMigrationProvider, Migrator, NO_MIGRATIONS } from 'kysely'\n   *\n   * const migrator = new Migrator({\n   *   db,\n   *   provider: new FileMigrationProvider({\n   *     fs,\n   *     // Path to the folder that contains all your migrations.\n   *     migrationFolder: 'some/path/to/migrations',\n   *     path,\n   *   })\n   * })\n   *\n   * await migrator.migrateTo(NO_MIGRATIONS)\n   * ```\n   */\n  async migrateTo(\n    targetMigrationName: string | NoMigrations,\n  ): Promise<MigrationResultSet> {\n    return this.#migrate(\n      ({\n        migrations,\n        executedMigrations,\n        pendingMigrations,\n      }: MigrationState) => {\n        if (\n          isObject(targetMigrationName) &&\n          targetMigrationName.__noMigrations__ === true\n        ) {\n          return { direction: 'Down', step: Infinity }\n        }\n\n        if (\n          !migrations.find((m) => m.name === (targetMigrationName as string))\n        ) {\n          throw new Error(`migration \"${targetMigrationName}\" doesn't exist`)\n        }\n\n        const executedIndex = executedMigrations.indexOf(\n          targetMigrationName as string,\n        )\n        const pendingIndex = pendingMigrations.findIndex(\n          (m) => m.name === (targetMigrationName as string),\n        )\n\n        if (executedIndex !== -1) {\n          return {\n            direction: 'Down',\n            step: executedMigrations.length - executedIndex - 1,\n          }\n        } else if (pendingIndex !== -1) {\n          return { direction: 'Up', step: pendingIndex + 1 }\n        } else {\n          throw new Error(\n            `migration \"${targetMigrationName}\" isn't executed or pending`,\n          )\n        }\n      },\n    )\n  }\n\n  /**\n   * Migrate one step up.\n   *\n   * This method returns a {@link MigrationResultSet} instance and _never_ throws.\n   * {@link MigrationResultSet.error} holds the error if something went wrong.\n   * {@link MigrationResultSet.results} contains information about which migrations\n   * were executed and which failed.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { promises as fs } from 'node:fs'\n   * import path from 'node:path'\n   * import { FileMigrationProvider, Migrator } from 'kysely'\n   *\n   * const migrator = new Migrator({\n   *   db,\n   *   provider: new FileMigrationProvider({\n   *     fs,\n   *     // Path to the folder that contains all your migrations.\n   *     migrationFolder: 'some/path/to/migrations',\n   *     path,\n   *   })\n   * })\n   *\n   * await migrator.migrateUp()\n   * ```\n   */\n  async migrateUp(): Promise<MigrationResultSet> {\n    return this.#migrate(() => ({ direction: 'Up', step: 1 }))\n  }\n\n  /**\n   * Migrate one step down.\n   *\n   * This method returns a {@link MigrationResultSet} instance and _never_ throws.\n   * {@link MigrationResultSet.error} holds the error if something went wrong.\n   * {@link MigrationResultSet.results} contains information about which migrations\n   * were executed and which failed.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { promises as fs } from 'node:fs'\n   * import path from 'node:path'\n   * import { FileMigrationProvider, Migrator } from 'kysely'\n   *\n   * const migrator = new Migrator({\n   *   db,\n   *   provider: new FileMigrationProvider({\n   *     fs,\n   *     // Path to the folder that contains all your migrations.\n   *     migrationFolder: 'some/path/to/migrations',\n   *     path,\n   *   })\n   * })\n   *\n   * await migrator.migrateDown()\n   * ```\n   */\n  async migrateDown(): Promise<MigrationResultSet> {\n    return this.#migrate(() => ({ direction: 'Down', step: 1 }))\n  }\n\n  async #migrate(\n    getMigrationDirectionAndStep: (state: MigrationState) => {\n      direction: MigrationDirection\n      step: number\n    },\n  ): Promise<MigrationResultSet> {\n    try {\n      await this.#ensureMigrationTableSchemaExists()\n      await this.#ensureMigrationTableExists()\n      await this.#ensureMigrationLockTableExists()\n      await this.#ensureLockRowExists()\n\n      return await this.#runMigrations(getMigrationDirectionAndStep)\n    } catch (error) {\n      if (error instanceof MigrationResultSetError) {\n        return error.resultSet\n      }\n\n      return { error }\n    }\n  }\n\n  get #migrationTableSchema(): string | undefined {\n    return this.#props.migrationTableSchema\n  }\n\n  get #migrationTable(): string {\n    return this.#props.migrationTableName ?? DEFAULT_MIGRATION_TABLE\n  }\n\n  get #migrationLockTable(): string {\n    return this.#props.migrationLockTableName ?? DEFAULT_MIGRATION_LOCK_TABLE\n  }\n\n  get #allowUnorderedMigrations(): boolean {\n    return (\n      this.#props.allowUnorderedMigrations ?? DEFAULT_ALLOW_UNORDERED_MIGRATIONS\n    )\n  }\n\n  get #schemaPlugin(): KyselyPlugin {\n    if (this.#migrationTableSchema) {\n      return new WithSchemaPlugin(this.#migrationTableSchema)\n    }\n\n    return new NoopPlugin()\n  }\n\n  async #ensureMigrationTableSchemaExists(): Promise<void> {\n    if (!this.#migrationTableSchema) {\n      // Use default schema. Nothing to do.\n      return\n    }\n\n    const schemaExists = await this.#doesSchemaExist()\n\n    if (schemaExists) {\n      return\n    }\n\n    try {\n      await this.#createIfNotExists(\n        this.#props.db.schema.createSchema(this.#migrationTableSchema),\n      )\n    } catch (error) {\n      const schemaExists = await this.#doesSchemaExist()\n\n      // At least on PostgreSQL, `if not exists` doesn't guarantee the `create schema`\n      // query doesn't throw if the schema already exits. That's why we check if\n      // the schema exist here and ignore the error if it does.\n      if (!schemaExists) {\n        throw error\n      }\n    }\n  }\n\n  async #ensureMigrationTableExists(): Promise<void> {\n    const tableExists = await this.#doesTableExist(this.#migrationTable)\n\n    if (tableExists) {\n      return\n    }\n\n    try {\n      await this.#createIfNotExists(\n        this.#props.db.schema\n          .withPlugin(this.#schemaPlugin)\n          .createTable(this.#migrationTable)\n          .addColumn('name', 'varchar(255)', (col) =>\n            col.notNull().primaryKey(),\n          )\n          // The migration run time as ISO string. This is not a real date type as we\n          // can't know which data type is supported by all future dialects.\n          .addColumn('timestamp', 'varchar(255)', (col) => col.notNull()),\n      )\n    } catch (error) {\n      const tableExists = await this.#doesTableExist(this.#migrationTable)\n\n      // At least on PostgreSQL, `if not exists` doesn't guarantee the `create table`\n      // query doesn't throw if the table already exits. That's why we check if\n      // the table exist here and ignore the error if it does.\n      if (!tableExists) {\n        throw error\n      }\n    }\n  }\n\n  async #ensureMigrationLockTableExists(): Promise<void> {\n    const tableExists = await this.#doesTableExist(this.#migrationLockTable)\n\n    if (tableExists) {\n      return\n    }\n\n    try {\n      await this.#createIfNotExists(\n        this.#props.db.schema\n          .withPlugin(this.#schemaPlugin)\n          .createTable(this.#migrationLockTable)\n          .addColumn('id', 'varchar(255)', (col) => col.notNull().primaryKey())\n          .addColumn('is_locked', 'integer', (col) =>\n            col.notNull().defaultTo(0),\n          ),\n      )\n    } catch (error) {\n      const tableExists = await this.#doesTableExist(this.#migrationLockTable)\n\n      // At least on PostgreSQL, `if not exists` doesn't guarantee the `create table`\n      // query doesn't throw if the table already exits. That's why we check if\n      // the table exist here and ignore the error if it does.\n      if (!tableExists) {\n        throw error\n      }\n    }\n  }\n\n  async #ensureLockRowExists(): Promise<void> {\n    const lockRowExists = await this.#doesLockRowExists()\n\n    if (lockRowExists) {\n      return\n    }\n\n    try {\n      await this.#props.db\n        .withPlugin(this.#schemaPlugin)\n        .insertInto(this.#migrationLockTable)\n        .values({ id: MIGRATION_LOCK_ID, is_locked: 0 })\n        .execute()\n    } catch (error) {\n      const lockRowExists = await this.#doesLockRowExists()\n\n      if (!lockRowExists) {\n        throw error\n      }\n    }\n  }\n\n  async #doesSchemaExist(): Promise<boolean> {\n    const schemas = await this.#props.db.introspection.getSchemas()\n\n    return schemas.some((it) => it.name === this.#migrationTableSchema)\n  }\n\n  async #doesTableExist(tableName: string): Promise<boolean> {\n    const schema = this.#migrationTableSchema\n\n    const tables = await this.#props.db.introspection.getTables({\n      withInternalKyselyTables: true,\n    })\n\n    return tables.some(\n      (it) => it.name === tableName && (!schema || it.schema === schema),\n    )\n  }\n\n  async #doesLockRowExists(): Promise<boolean> {\n    const lockRow = await this.#props.db\n      .withPlugin(this.#schemaPlugin)\n      .selectFrom(this.#migrationLockTable)\n      .where('id', '=', MIGRATION_LOCK_ID)\n      .select('id')\n      .executeTakeFirst()\n\n    return !!lockRow\n  }\n\n  async #runMigrations(\n    getMigrationDirectionAndStep: (state: MigrationState) => {\n      direction: MigrationDirection\n      step: number\n    },\n  ): Promise<MigrationResultSet> {\n    const adapter = this.#props.db.getExecutor().adapter\n\n    const lockOptions: MigrationLockOptions = freeze({\n      lockTable:\n        this.#props.migrationLockTableName ?? DEFAULT_MIGRATION_LOCK_TABLE,\n      lockRowId: MIGRATION_LOCK_ID,\n      lockTableSchema: this.#props.migrationTableSchema,\n    })\n\n    const run = async (db: Kysely<any>): Promise<MigrationResultSet> => {\n      try {\n        await adapter.acquireMigrationLock(db, lockOptions)\n        const state = await this.#getState(db)\n\n        if (state.migrations.length === 0) {\n          return { results: [] }\n        }\n\n        const { direction, step } = getMigrationDirectionAndStep(state)\n\n        if (step <= 0) {\n          return { results: [] }\n        }\n\n        if (direction === 'Down') {\n          return await this.#migrateDown(db, state, step)\n        } else if (direction === 'Up') {\n          return await this.#migrateUp(db, state, step)\n        }\n\n        return { results: [] }\n      } finally {\n        await adapter.releaseMigrationLock(db, lockOptions)\n      }\n    }\n\n    if (adapter.supportsTransactionalDdl && !this.#props.disableTransactions) {\n      return this.#props.db.transaction().execute(run)\n    } else {\n      return this.#props.db.connection().execute(run)\n    }\n  }\n\n  async #getState(db: Kysely<any>): Promise<MigrationState> {\n    const migrations = await this.#resolveMigrations()\n    const executedMigrations = await this.#getExecutedMigrations(db)\n\n    this.#ensureNoMissingMigrations(migrations, executedMigrations)\n    if (!this.#allowUnorderedMigrations) {\n      this.#ensureMigrationsInOrder(migrations, executedMigrations)\n    }\n\n    const pendingMigrations = this.#getPendingMigrations(\n      migrations,\n      executedMigrations,\n    )\n\n    return freeze({\n      migrations,\n      executedMigrations,\n      lastMigration: getLast(executedMigrations),\n      pendingMigrations,\n    })\n  }\n\n  #getPendingMigrations(\n    migrations: ReadonlyArray<NamedMigration>,\n    executedMigrations: ReadonlyArray<string>,\n  ): ReadonlyArray<NamedMigration> {\n    return migrations.filter((migration) => {\n      return !executedMigrations.includes(migration.name)\n    })\n  }\n\n  async #resolveMigrations(): Promise<ReadonlyArray<NamedMigration>> {\n    const allMigrations = await this.#props.provider.getMigrations()\n\n    return Object.keys(allMigrations)\n      .sort()\n      .map((name) => ({\n        ...allMigrations[name],\n        name,\n      }))\n  }\n\n  async #getExecutedMigrations(\n    db: Kysely<any>,\n  ): Promise<ReadonlyArray<string>> {\n    const executedMigrations = await db\n      .withPlugin(this.#schemaPlugin)\n      .selectFrom(this.#migrationTable)\n      .select(['name', 'timestamp'])\n      .$narrowType<{ name: string; timestamp: string }>()\n      .execute()\n\n    const nameComparator =\n      this.#props.nameComparator || ((a, b) => a.localeCompare(b))\n\n    return (\n      executedMigrations\n        // https://github.com/kysely-org/kysely/issues/843\n        .sort((a, b) => {\n          if (a.timestamp === b.timestamp) {\n            return nameComparator(a.name, b.name)\n          }\n\n          return (\n            new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()\n          )\n        })\n        .map((it) => it.name)\n    )\n  }\n\n  #ensureNoMissingMigrations(\n    migrations: ReadonlyArray<NamedMigration>,\n    executedMigrations: ReadonlyArray<string>,\n  ) {\n    // Ensure all executed migrations exist in the `migrations` list.\n    for (const executed of executedMigrations) {\n      if (!migrations.some((it) => it.name === executed)) {\n        throw new Error(\n          `corrupted migrations: previously executed migration ${executed} is missing`,\n        )\n      }\n    }\n  }\n\n  #ensureMigrationsInOrder(\n    migrations: ReadonlyArray<NamedMigration>,\n    executedMigrations: ReadonlyArray<string>,\n  ) {\n    // Ensure the executed migrations are the first ones in the migration list.\n    for (let i = 0; i < executedMigrations.length; ++i) {\n      if (migrations[i].name !== executedMigrations[i]) {\n        throw new Error(\n          `corrupted migrations: expected previously executed migration ${executedMigrations[i]} to be at index ${i} but ${migrations[i].name} was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.`,\n        )\n      }\n    }\n  }\n\n  async #migrateDown(\n    db: Kysely<any>,\n    state: MigrationState,\n    step: number,\n  ): Promise<MigrationResultSet> {\n    const migrationsToRollback: ReadonlyArray<NamedMigration> =\n      state.executedMigrations\n        .slice()\n        .reverse()\n        .slice(0, step)\n        .map((name) => {\n          return state.migrations.find((it) => it.name === name)!\n        })\n\n    const results: MigrationResult[] = migrationsToRollback.map((migration) => {\n      return {\n        migrationName: migration.name,\n        direction: 'Down',\n        status: 'NotExecuted',\n      }\n    })\n\n    for (let i = 0; i < results.length; ++i) {\n      const migration = migrationsToRollback[i]\n\n      try {\n        if (migration.down) {\n          await migration.down(db)\n          await db\n            .withPlugin(this.#schemaPlugin)\n            .deleteFrom(this.#migrationTable)\n            .where('name', '=', migration.name)\n            .execute()\n\n          results[i] = {\n            migrationName: migration.name,\n            direction: 'Down',\n            status: 'Success',\n          }\n        }\n      } catch (error) {\n        results[i] = {\n          migrationName: migration.name,\n          direction: 'Down',\n          status: 'Error',\n        }\n\n        throw new MigrationResultSetError({\n          error,\n          results,\n        })\n      }\n    }\n\n    return { results }\n  }\n\n  async #migrateUp(\n    db: Kysely<any>,\n    state: MigrationState,\n    step: number,\n  ): Promise<MigrationResultSet> {\n    const migrationsToRun: ReadonlyArray<NamedMigration> =\n      state.pendingMigrations.slice(0, step)\n\n    const results: MigrationResult[] = migrationsToRun.map((migration) => {\n      return {\n        migrationName: migration.name,\n        direction: 'Up',\n        status: 'NotExecuted',\n      }\n    })\n\n    for (let i = 0; i < results.length; i++) {\n      const migration = state.pendingMigrations[i]\n\n      try {\n        await migration.up(db)\n        await db\n          .withPlugin(this.#schemaPlugin)\n          .insertInto(this.#migrationTable)\n          .values({\n            name: migration.name,\n            timestamp: new Date().toISOString(),\n          })\n          .execute()\n\n        results[i] = {\n          migrationName: migration.name,\n          direction: 'Up',\n          status: 'Success',\n        }\n      } catch (error) {\n        results[i] = {\n          migrationName: migration.name,\n          direction: 'Up',\n          status: 'Error',\n        }\n\n        throw new MigrationResultSetError({\n          error,\n          results,\n        })\n      }\n    }\n\n    return { results }\n  }\n\n  async #createIfNotExists(\n    qb: CreateTableBuilder<any, any> | CreateSchemaBuilder,\n  ): Promise<void> {\n    if (this.#props.db.getExecutor().adapter.supportsCreateIfNotExists) {\n      qb = qb.ifNotExists()\n    }\n\n    await qb.execute()\n  }\n}\n\nexport interface MigratorProps {\n  readonly db: Kysely<any>\n  readonly provider: MigrationProvider\n\n  /**\n   * The name of the internal migration table. Defaults to `kysely_migration`.\n   *\n   * If you do specify this, you need to ALWAYS use the same value. Kysely doesn't\n   * support changing the table on the fly. If you run the migrator even once with a\n   * table name X and then change the table name to Y, kysely will create a new empty\n   * migration table and attempt to run the migrations again, which will obviously\n   * fail.\n   *\n   * If you do specify this, ALWAYS ALWAYS use the same value from the beginning of\n   * the project, to the end of time or prepare to manually migrate the migration\n   * tables.\n   */\n  readonly migrationTableName?: string\n\n  /**\n   * The name of the internal migration lock table. Defaults to `kysely_migration_lock`.\n   *\n   * If you do specify this, you need to ALWAYS use the same value. Kysely doesn't\n   * support changing the table on the fly. If you run the migrator even once with a\n   * table name X and then change the table name to Y, kysely will create a new empty\n   * lock table.\n   *\n   * If you do specify this, ALWAYS ALWAYS use the same value from the beginning of\n   * the project, to the end of time or prepare to manually migrate the migration\n   * tables.\n   */\n  readonly migrationLockTableName?: string\n\n  /**\n   * The schema of the internal migration tables. Defaults to the default schema\n   * on dialects that support schemas.\n   *\n   * If you do specify this, you need to ALWAYS use the same value. Kysely doesn't\n   * support changing the schema on the fly. If you run the migrator even once with a\n   * schema name X and then change the schema name to Y, kysely will create a new empty\n   * migration tables in the new schema and attempt to run the migrations again, which\n   * will obviously fail.\n   *\n   * If you do specify this, ALWAYS ALWAYS use the same value from the beginning of\n   * the project, to the end of time or prepare to manually migrate the migration\n   * tables.\n   *\n   * This only works on postgres and mssql.\n   */\n  readonly migrationTableSchema?: string\n\n  /**\n   * Enforces whether or not migrations must be run in alpha-numeric order.\n   *\n   * When false, migrations must be run in their exact alpha-numeric order.\n   * This is checked against the migrations already run in the database\n   * (`migrationTableName`). This ensures your migrations are always run in\n   * the same order and is the safest option.\n   *\n   * When true, migrations are still run in alpha-numeric order, but\n   * the order is not checked against already-run migrations in the database.\n   * Kysely will simply run all migrations that haven't run yet, in alpha-numeric\n   * order.\n   */\n  readonly allowUnorderedMigrations?: boolean\n\n  /**\n   * A function that compares migration names, used when sorting migrations in\n   * ascending order.\n   *\n   * Default is `name0.localeCompare(name1)`.\n   */\n  readonly nameComparator?: (name0: string, name1: string) => number\n\n  /**\n   * When `true`, don't run migrations in transactions even if the dialect supports transactional DDL.\n   *\n   * Default is `false`.\n   *\n   * This is useful when some migrations include queries that would fail otherwise.\n   */\n  readonly disableTransactions?: boolean\n}\n\n/**\n * All migration methods ({@link Migrator.migrateTo | migrateTo},\n * {@link Migrator.migrateToLatest | migrateToLatest} etc.) never\n * throw but return this object instead.\n */\nexport interface MigrationResultSet {\n  /**\n   * This is defined if something went wrong.\n   *\n   * An error may have occurred in one of the migrations in which case the\n   * {@link results} list contains an item with `status === 'Error'` to\n   * indicate which migration failed.\n   *\n   * An error may also have occurred before Kysely was able to figure out\n   * which migrations should be executed, in which case the {@link results}\n   * list is undefined.\n   */\n  readonly error?: unknown\n\n  /**\n   * {@link MigrationResult} for each individual migration that was supposed\n   * to be executed by the operation.\n   *\n   * If all went well, each result's `status` is `Success`. If some migration\n   * failed, the failed migration's result's `status` is `Error` and all\n   * results after that one have `status` ´NotExecuted`.\n   *\n   * This property can be undefined if an error occurred before Kysely was\n   * able to figure out which migrations should be executed.\n   *\n   * If this list is empty, there were no migrations to execute.\n   */\n  readonly results?: MigrationResult[]\n}\n\ntype MigrationDirection = 'Up' | 'Down'\n\nexport interface MigrationResult {\n  readonly migrationName: string\n\n  /**\n   * The direction in which this migration was executed.\n   */\n  readonly direction: MigrationDirection\n\n  /**\n   * The execution status.\n   *\n   *  - `Success` means the migration was successfully executed. Note that\n   *    if any of the later migrations in the {@link MigrationResultSet.results}\n   *    list failed (have status `Error`) AND the dialect supports transactional\n   *    DDL, even the successfull migrations were rolled back.\n   *\n   *  - `Error` means the migration failed. In this case the\n   *    {@link MigrationResultSet.error} contains the error.\n   *\n   *  - `NotExecuted` means that the migration was supposed to be executed\n   *    but wasn't because an earlier migration failed.\n   */\n  readonly status: 'Success' | 'Error' | 'NotExecuted'\n}\n\nexport interface MigrationProvider {\n  /**\n   * Returns all migrations, old and new.\n   *\n   * For example if you have your migrations in a folder as separate files,\n   * you can implement this method to return all migration in that folder\n   * as {@link Migration} objects.\n   *\n   * Kysely already has a built-in {@link FileMigrationProvider} for node.js\n   * that does exactly that.\n   *\n   * The keys of the returned object are migration names and values are the\n   * migrations. The order of the migrations is determined by the alphabetical\n   * order of the migration names. The items in the object don't need to be\n   * sorted, they are sorted by Kysely.\n   */\n  getMigrations(): Promise<Record<string, Migration>>\n}\n\n/**\n * Type for the {@link NO_MIGRATIONS} constant. Never create one of these.\n */\nexport interface NoMigrations {\n  readonly __noMigrations__: true\n}\n\nexport interface MigrationInfo {\n  /**\n   * Name of the migration.\n   */\n  name: string\n\n  /**\n   * The actual migration.\n   */\n  migration: Migration\n\n  /**\n   * When was the migration executed.\n   *\n   * If this is undefined, the migration hasn't been executed yet.\n   */\n  executedAt?: Date\n}\n\ninterface NamedMigration extends Migration {\n  readonly name: string\n}\n\ninterface MigrationState {\n  // All migrations sorted by name.\n  readonly migrations: ReadonlyArray<NamedMigration>\n\n  // Names of executed migrations sorted by execution timestamp\n  readonly executedMigrations: ReadonlyArray<string>\n\n  // Name of the last executed migration.\n  readonly lastMigration?: string\n\n  // Migrations that have not yet ran\n  readonly pendingMigrations: ReadonlyArray<NamedMigration>\n}\n\nclass MigrationResultSetError extends Error {\n  readonly #resultSet: MigrationResultSet\n\n  constructor(result: MigrationResultSet) {\n    super()\n    this.#resultSet = result\n  }\n\n  get resultSet(): MigrationResultSet {\n    return this.#resultSet\n  }\n}\n"
  },
  {
    "path": "src/operation-node/add-column-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { ColumnDefinitionNode } from './column-definition-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface AddColumnNode extends OperationNode {\n  readonly kind: 'AddColumnNode'\n  readonly column: ColumnDefinitionNode\n}\n\ntype AddColumnNodeFactory = Readonly<{\n  is(node: OperationNode): node is AddColumnNode\n  create(column: ColumnDefinitionNode): Readonly<AddColumnNode>\n}>\n\n/**\n * @internal\n */\nexport const AddColumnNode: AddColumnNodeFactory = freeze<AddColumnNodeFactory>(\n  {\n    is(node): node is AddColumnNode {\n      return node.kind === 'AddColumnNode'\n    },\n\n    create(column) {\n      return freeze({\n        kind: 'AddColumnNode',\n        column,\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/operation-node/add-constraint-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { ConstraintNode } from './constraint-node.js'\n\nexport interface AddConstraintNode extends OperationNode {\n  readonly kind: 'AddConstraintNode'\n  readonly constraint: ConstraintNode\n}\n\ntype AddConstraintNodeFactory = Readonly<{\n  is(node: OperationNode): node is AddConstraintNode\n  create(constraint: ConstraintNode): Readonly<AddConstraintNode>\n}>\n\n/**\n * @internal\n */\nexport const AddConstraintNode: AddConstraintNodeFactory =\n  freeze<AddConstraintNodeFactory>({\n    is(node): node is AddConstraintNode {\n      return node.kind === 'AddConstraintNode'\n    },\n\n    create(constraint) {\n      return freeze({\n        kind: 'AddConstraintNode',\n        constraint,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/add-index-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { RawNode } from './raw-node.js'\n\nexport type AddIndexNodeProps = Omit<AddIndexNode, 'kind' | 'name'>\n\nexport interface AddIndexNode extends OperationNode {\n  readonly kind: 'AddIndexNode'\n  readonly name: IdentifierNode\n  readonly columns?: OperationNode[]\n  readonly unique?: boolean\n  readonly using?: RawNode\n  readonly ifNotExists?: boolean\n}\n\ntype AddIndexNodeFactory = Readonly<{\n  is(node: OperationNode): node is AddIndexNode\n  create(name: string): Readonly<AddIndexNode>\n  cloneWith(\n    node: AddIndexNode,\n    props: Omit<AddIndexNode, 'kind' | 'name'>,\n  ): Readonly<AddIndexNode>\n  cloneWithColumns(\n    node: AddIndexNode,\n    columns: OperationNode[],\n  ): Readonly<AddIndexNode>\n}>\n\n/**\n * @internal\n */\nexport const AddIndexNode: AddIndexNodeFactory = freeze<AddIndexNodeFactory>({\n  is(node): node is AddIndexNode {\n    return node.kind === 'AddIndexNode'\n  },\n\n  create(name) {\n    return freeze({\n      kind: 'AddIndexNode',\n      name: IdentifierNode.create(name),\n    })\n  },\n\n  cloneWith(node, props) {\n    return freeze({\n      ...node,\n      ...props,\n    })\n  },\n\n  cloneWithColumns(node, columns) {\n    return freeze({\n      ...node,\n      columns: [...(node.columns || []), ...columns],\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/aggregate-function-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { OverNode } from './over-node.js'\nimport { WhereNode } from './where-node.js'\nimport { OrderByNode } from './order-by-node.js'\nimport type { OrderByItemNode } from './order-by-item-node.js'\n\nexport interface AggregateFunctionNode extends OperationNode {\n  readonly kind: 'AggregateFunctionNode'\n  readonly func: string\n  readonly aggregated: readonly OperationNode[]\n  readonly distinct?: boolean\n  readonly orderBy?: OrderByNode\n  readonly withinGroup?: OrderByNode\n  readonly filter?: WhereNode\n  readonly over?: OverNode\n}\n\ntype AggregateFunctionNodeFactory = Readonly<{\n  is(node: OperationNode): node is AggregateFunctionNode\n  create(\n    aggregateFunction: string,\n    aggregated?: readonly OperationNode[],\n  ): Readonly<AggregateFunctionNode>\n  cloneWithDistinct(\n    aggregateFunctionNode: AggregateFunctionNode,\n  ): Readonly<AggregateFunctionNode>\n  cloneWithOrderBy(\n    aggregateFunctionNode: AggregateFunctionNode,\n    orderItems: ReadonlyArray<OrderByItemNode>,\n    withinGroup?: boolean,\n  ): Readonly<AggregateFunctionNode>\n  cloneWithFilter(\n    aggregateFunctionNode: AggregateFunctionNode,\n    filter: OperationNode,\n  ): Readonly<AggregateFunctionNode>\n  cloneWithOrFilter(\n    aggregateFunctionNode: AggregateFunctionNode,\n    filter: OperationNode,\n  ): Readonly<AggregateFunctionNode>\n  cloneWithOver(\n    aggregateFunctionNode: AggregateFunctionNode,\n    over?: OverNode,\n  ): Readonly<AggregateFunctionNode>\n}>\n\n/**\n * @internal\n */\nexport const AggregateFunctionNode: AggregateFunctionNodeFactory =\n  freeze<AggregateFunctionNodeFactory>({\n    is(node): node is AggregateFunctionNode {\n      return node.kind === 'AggregateFunctionNode'\n    },\n\n    create(aggregateFunction, aggregated = []) {\n      return freeze({\n        kind: 'AggregateFunctionNode',\n        func: aggregateFunction,\n        aggregated,\n      })\n    },\n\n    cloneWithDistinct(aggregateFunctionNode) {\n      return freeze({\n        ...aggregateFunctionNode,\n        distinct: true,\n      })\n    },\n\n    cloneWithOrderBy(aggregateFunctionNode, orderItems, withinGroup = false) {\n      const prop = withinGroup ? 'withinGroup' : 'orderBy'\n\n      return freeze({\n        ...aggregateFunctionNode,\n        [prop]: aggregateFunctionNode[prop]\n          ? OrderByNode.cloneWithItems(aggregateFunctionNode[prop], orderItems)\n          : OrderByNode.create(orderItems),\n      })\n    },\n\n    cloneWithFilter(aggregateFunctionNode, filter) {\n      return freeze({\n        ...aggregateFunctionNode,\n        filter: aggregateFunctionNode.filter\n          ? WhereNode.cloneWithOperation(\n              aggregateFunctionNode.filter,\n              'And',\n              filter,\n            )\n          : WhereNode.create(filter),\n      })\n    },\n\n    cloneWithOrFilter(aggregateFunctionNode, filter) {\n      return freeze({\n        ...aggregateFunctionNode,\n        filter: aggregateFunctionNode.filter\n          ? WhereNode.cloneWithOperation(\n              aggregateFunctionNode.filter,\n              'Or',\n              filter,\n            )\n          : WhereNode.create(filter),\n      })\n    },\n\n    cloneWithOver(aggregateFunctionNode, over?) {\n      return freeze({\n        ...aggregateFunctionNode,\n        over,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/alias-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface AliasNode extends OperationNode {\n  readonly kind: 'AliasNode'\n  readonly node: OperationNode\n  readonly alias: OperationNode\n}\n\ntype AliasNodeFactory = Readonly<{\n  is(node: OperationNode): node is AliasNode\n  create(node: OperationNode, alias: OperationNode): Readonly<AliasNode>\n}>\n\n/**\n * @internal\n */\nexport const AliasNode: AliasNodeFactory = freeze<AliasNodeFactory>({\n  is(node): node is AliasNode {\n    return node.kind === 'AliasNode'\n  },\n\n  create(node, alias) {\n    return freeze({\n      kind: 'AliasNode',\n      node,\n      alias,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/alter-column-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport { ColumnNode } from './column-node.js'\nimport type { RawNode } from './raw-node.js'\n\nexport type AlterColumnNodeProps = Omit<AlterColumnNode, 'kind' | 'column'>\n\nexport interface AlterColumnNode extends OperationNode {\n  readonly kind: 'AlterColumnNode'\n  readonly column: ColumnNode\n  readonly dataType?: OperationNode\n  readonly dataTypeExpression?: RawNode\n  readonly setDefault?: OperationNode\n  readonly dropDefault?: true\n  readonly setNotNull?: true\n  readonly dropNotNull?: true\n}\n\ntype AlterColumnNodeFactory = Readonly<{\n  is(node: OperationNode): node is AlterColumnNode\n  create<T extends keyof AlterColumnNodeProps>(\n    column: string,\n    prop: T,\n    value: Required<AlterColumnNodeProps>[T],\n  ): Readonly<AlterColumnNode>\n}>\n\n/**\n * @internal\n */\nexport const AlterColumnNode: AlterColumnNodeFactory =\n  freeze<AlterColumnNodeFactory>({\n    is(node): node is AlterColumnNode {\n      return node.kind === 'AlterColumnNode'\n    },\n\n    create(column, prop, value) {\n      return freeze({\n        kind: 'AlterColumnNode',\n        column: ColumnNode.create(column),\n        [prop]: value,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/alter-table-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { AddColumnNode } from './add-column-node.js'\nimport type { DropColumnNode } from './drop-column-node.js'\nimport type { TableNode } from './table-node.js'\nimport type { IdentifierNode } from './identifier-node.js'\nimport type { RenameColumnNode } from './rename-column-node.js'\nimport type { AlterColumnNode } from './alter-column-node.js'\nimport type { AddConstraintNode } from './add-constraint-node.js'\nimport type { DropConstraintNode } from './drop-constraint-node.js'\nimport type { ModifyColumnNode } from './modify-column-node.js'\nimport type { DropIndexNode } from './drop-index-node.js'\nimport type { AddIndexNode } from './add-index-node.js'\nimport type { RenameConstraintNode } from './rename-constraint-node.js'\n\nexport type AlterTableNodeTableProps = Pick<\n  AlterTableNode,\n  | 'renameTo'\n  | 'setSchema'\n  | 'addConstraint'\n  | 'dropConstraint'\n  | 'addIndex'\n  | 'dropIndex'\n  | 'renameConstraint'\n>\n\nexport type AlterTableColumnAlterationNode =\n  | RenameColumnNode\n  | AddColumnNode\n  | DropColumnNode\n  | AlterColumnNode\n  | ModifyColumnNode\n\nexport interface AlterTableNode extends OperationNode {\n  readonly kind: 'AlterTableNode'\n  readonly table: TableNode\n  readonly renameTo?: TableNode\n  readonly setSchema?: IdentifierNode\n  readonly columnAlterations?: ReadonlyArray<AlterTableColumnAlterationNode>\n  readonly addConstraint?: AddConstraintNode\n  readonly dropConstraint?: DropConstraintNode\n  readonly renameConstraint?: RenameConstraintNode\n  readonly addIndex?: AddIndexNode\n  readonly dropIndex?: DropIndexNode\n}\n\ntype AlterTableNodeFactory = Readonly<{\n  is(node: OperationNode): node is AlterTableNode\n  create(table: TableNode): Readonly<AlterTableNode>\n  cloneWithTableProps(\n    node: AlterTableNode,\n    props: AlterTableNodeTableProps,\n  ): Readonly<AlterTableNode>\n  cloneWithColumnAlteration(\n    node: AlterTableNode,\n    columnAlteration: AlterTableColumnAlterationNode,\n  ): Readonly<AlterTableNode>\n}>\n\n/**\n * @internal\n */\nexport const AlterTableNode: AlterTableNodeFactory =\n  freeze<AlterTableNodeFactory>({\n    is(node): node is AlterTableNode {\n      return node.kind === 'AlterTableNode'\n    },\n\n    create(table) {\n      return freeze({\n        kind: 'AlterTableNode',\n        table,\n      })\n    },\n\n    cloneWithTableProps(node, props) {\n      return freeze({\n        ...node,\n        ...props,\n      })\n    },\n\n    cloneWithColumnAlteration(node, columnAlteration) {\n      return freeze({\n        ...node,\n        columnAlterations: node.columnAlterations\n          ? [...node.columnAlterations, columnAlteration]\n          : [columnAlteration],\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/and-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport interface AndNode extends OperationNode {\n  readonly kind: 'AndNode'\n  readonly left: OperationNode\n  readonly right: OperationNode\n}\n\ntype AndNodeFactory = Readonly<{\n  is(node: OperationNode): node is AndNode\n  create(left: OperationNode, right: OperationNode): Readonly<AndNode>\n}>\n\n/**\n * @internal\n */\nexport const AndNode: AndNodeFactory = freeze<AndNodeFactory>({\n  is(node): node is AndNode {\n    return node.kind === 'AndNode'\n  },\n\n  create(left, right) {\n    return freeze({\n      kind: 'AndNode',\n      left,\n      right,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/binary-operation-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface BinaryOperationNode extends OperationNode {\n  readonly kind: 'BinaryOperationNode'\n  readonly leftOperand: OperationNode\n  readonly operator: OperationNode\n  readonly rightOperand: OperationNode\n}\n\ntype BinaryOperationNodeFactory = Readonly<{\n  is(node: OperationNode): node is BinaryOperationNode\n  create(\n    leftOperand: OperationNode,\n    operator: OperationNode,\n    rightOperand: OperationNode,\n  ): Readonly<BinaryOperationNode>\n}>\n\n/**\n * @internal\n */\nexport const BinaryOperationNode: BinaryOperationNodeFactory =\n  freeze<BinaryOperationNodeFactory>({\n    is(node): node is BinaryOperationNode {\n      return node.kind === 'BinaryOperationNode'\n    },\n\n    create(leftOperand, operator, rightOperand) {\n      return freeze({\n        kind: 'BinaryOperationNode',\n        leftOperand,\n        operator,\n        rightOperand,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/case-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport { WhenNode } from './when-node.js'\n\nexport interface CaseNode extends OperationNode {\n  readonly kind: 'CaseNode'\n  readonly value?: OperationNode\n  readonly when?: ReadonlyArray<WhenNode>\n  readonly else?: OperationNode\n  readonly isStatement?: boolean\n}\n\ntype CaseNodeFactory = Readonly<{\n  is(node: OperationNode): node is CaseNode\n  create(value?: OperationNode): Readonly<CaseNode>\n  cloneWithWhen(caseNode: CaseNode, when: WhenNode): Readonly<CaseNode>\n  cloneWithThen(caseNode: CaseNode, then: OperationNode): Readonly<CaseNode>\n  cloneWith(\n    caseNode: CaseNode,\n    props: Partial<Pick<CaseNode, 'else' | 'isStatement'>>,\n  ): Readonly<CaseNode>\n}>\n\n/**\n * @internal\n */\nexport const CaseNode: CaseNodeFactory = freeze<CaseNodeFactory>({\n  is(node): node is CaseNode {\n    return node.kind === 'CaseNode'\n  },\n\n  create(value?) {\n    return freeze({\n      kind: 'CaseNode',\n      value,\n    })\n  },\n\n  cloneWithWhen(caseNode, when) {\n    return freeze({\n      ...caseNode,\n      when: freeze(caseNode.when ? [...caseNode.when, when] : [when]),\n    })\n  },\n\n  cloneWithThen(caseNode, then) {\n    return freeze({\n      ...caseNode,\n      when: caseNode.when\n        ? freeze([\n            ...caseNode.when.slice(0, -1),\n            WhenNode.cloneWithResult(\n              caseNode.when[caseNode.when.length - 1],\n              then,\n            ),\n          ])\n        : undefined,\n    })\n  },\n\n  cloneWith(caseNode, props) {\n    return freeze({\n      ...caseNode,\n      ...props,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/cast-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport interface CastNode extends OperationNode {\n  readonly kind: 'CastNode'\n  readonly expression: OperationNode\n  readonly dataType: OperationNode\n}\n\ntype CastNodeFactory = Readonly<{\n  is(node: OperationNode): node is CastNode\n  create(expression: OperationNode, dataType: OperationNode): Readonly<CastNode>\n}>\n\n/**\n * @internal\n */\nexport const CastNode: CastNodeFactory = freeze<CastNodeFactory>({\n  is(node): node is CastNode {\n    return node.kind === 'CastNode'\n  },\n\n  create(expression, dataType) {\n    return freeze({\n      kind: 'CastNode',\n      expression,\n      dataType,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/check-constraint-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\n\nexport interface CheckConstraintNode extends OperationNode {\n  readonly kind: 'CheckConstraintNode'\n  readonly expression: OperationNode\n  readonly name?: IdentifierNode\n}\n\ntype CheckConstraintNodeFactory = Readonly<{\n  is(node: OperationNode): node is CheckConstraintNode\n  create(\n    expression: OperationNode,\n    constraintName?: string,\n  ): Readonly<CheckConstraintNode>\n}>\n\n/**\n * @internal\n */\nexport const CheckConstraintNode: CheckConstraintNodeFactory =\n  freeze<CheckConstraintNodeFactory>({\n    is(node): node is CheckConstraintNode {\n      return node.kind === 'CheckConstraintNode'\n    },\n\n    create(expression, constraintName?) {\n      return freeze({\n        kind: 'CheckConstraintNode',\n        expression,\n        name: constraintName\n          ? IdentifierNode.create(constraintName)\n          : undefined,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/collate-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface CollateNode extends OperationNode {\n  readonly kind: 'CollateNode'\n  readonly collation: IdentifierNode\n}\n\ntype CollateNodeFactory = Readonly<{\n  is(node: OperationNode): node is CollateNode\n  create(collation: string): Readonly<CollateNode>\n}>\n\n/**\n * @internal\n */\nexport const CollateNode: CollateNodeFactory = freeze<CollateNodeFactory>({\n  is(node): node is CollateNode {\n    return node.kind === 'CollateNode'\n  },\n\n  create(collation) {\n    return freeze({\n      kind: 'CollateNode',\n      collation: IdentifierNode.create(collation),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/column-definition-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { CheckConstraintNode } from './check-constraint-node.js'\nimport { ColumnNode } from './column-node.js'\nimport type { DefaultValueNode } from './default-value-node.js'\nimport type { GeneratedNode } from './generated-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { ReferencesNode } from './references-node.js'\n\nexport type ColumnDefinitionNodeProps = Omit<\n  Partial<ColumnDefinitionNode>,\n  'kind' | 'dataType'\n>\n\nexport interface ColumnDefinitionNode extends OperationNode {\n  readonly kind: 'ColumnDefinitionNode'\n  readonly column: ColumnNode\n  readonly dataType: OperationNode\n  readonly references?: ReferencesNode\n  readonly primaryKey?: boolean\n  readonly autoIncrement?: boolean\n  readonly unique?: boolean\n  readonly notNull?: boolean\n  readonly defaultTo?: DefaultValueNode\n  readonly check?: CheckConstraintNode\n  readonly generated?: GeneratedNode\n  readonly unsigned?: boolean\n  readonly frontModifiers?: ReadonlyArray<OperationNode>\n  readonly endModifiers?: ReadonlyArray<OperationNode>\n  readonly nullsNotDistinct?: boolean\n  readonly identity?: boolean\n  readonly ifNotExists?: boolean\n}\n\ntype ColumnDefinitionNodeFactory = Readonly<{\n  is(node: OperationNode): node is ColumnDefinitionNode\n  create(\n    column: string,\n    dataType: OperationNode,\n  ): Readonly<ColumnDefinitionNode>\n  cloneWithFrontModifier(\n    node: ColumnDefinitionNode,\n    modifier: OperationNode,\n  ): Readonly<ColumnDefinitionNode>\n  cloneWithEndModifier(\n    node: ColumnDefinitionNode,\n    modifier: OperationNode,\n  ): Readonly<ColumnDefinitionNode>\n  cloneWith(\n    node: ColumnDefinitionNode,\n    props: ColumnDefinitionNodeProps,\n  ): Readonly<ColumnDefinitionNode>\n}>\n\n/**\n * @internal\n */\nexport const ColumnDefinitionNode: ColumnDefinitionNodeFactory =\n  freeze<ColumnDefinitionNodeFactory>({\n    is(node): node is ColumnDefinitionNode {\n      return node.kind === 'ColumnDefinitionNode'\n    },\n\n    create(column, dataType) {\n      return freeze({\n        kind: 'ColumnDefinitionNode',\n        column: ColumnNode.create(column),\n        dataType,\n      })\n    },\n\n    cloneWithFrontModifier(node, modifier) {\n      return freeze({\n        ...node,\n        frontModifiers: node.frontModifiers\n          ? freeze([...node.frontModifiers, modifier])\n          : [modifier],\n      })\n    },\n\n    cloneWithEndModifier(node, modifier) {\n      return freeze({\n        ...node,\n        endModifiers: node.endModifiers\n          ? freeze([...node.endModifiers, modifier])\n          : [modifier],\n      })\n    },\n\n    cloneWith(node, props) {\n      return freeze({\n        ...node,\n        ...props,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/column-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface ColumnNode extends OperationNode {\n  readonly kind: 'ColumnNode'\n  readonly column: IdentifierNode\n}\n\ntype ColumnNodeFactory = Readonly<{\n  is(node: OperationNode): node is ColumnNode\n  create(column: string): Readonly<ColumnNode>\n}>\n\n/**\n * @internal\n */\nexport const ColumnNode: ColumnNodeFactory = freeze<ColumnNodeFactory>({\n  is(node): node is ColumnNode {\n    return node.kind === 'ColumnNode'\n  },\n\n  create(column) {\n    return freeze({\n      kind: 'ColumnNode',\n      column: IdentifierNode.create(column),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/column-update-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface ColumnUpdateNode extends OperationNode {\n  readonly kind: 'ColumnUpdateNode'\n  readonly column: OperationNode\n  readonly value: OperationNode\n}\n\ntype ColumnUpdateNodeFactory = Readonly<{\n  is(node: OperationNode): node is ColumnUpdateNode\n  create(\n    column: OperationNode,\n    value: OperationNode,\n  ): Readonly<ColumnUpdateNode>\n}>\n\n/**\n * @internal\n */\nexport const ColumnUpdateNode: ColumnUpdateNodeFactory =\n  freeze<ColumnUpdateNodeFactory>({\n    is(node): node is ColumnUpdateNode {\n      return node.kind === 'ColumnUpdateNode'\n    },\n\n    create(column, value) {\n      return freeze({\n        kind: 'ColumnUpdateNode',\n        column,\n        value,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/common-table-expression-name-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { ColumnNode } from './column-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport { TableNode } from './table-node.js'\n\nexport interface CommonTableExpressionNameNode extends OperationNode {\n  readonly kind: 'CommonTableExpressionNameNode'\n  readonly table: TableNode\n  readonly columns?: ReadonlyArray<ColumnNode>\n}\n\ntype CommonTableExpressionNameNodeFactory = Readonly<{\n  is(node: OperationNode): node is CommonTableExpressionNameNode\n  create(\n    tableName: string,\n    columnNames?: ReadonlyArray<string>,\n  ): Readonly<CommonTableExpressionNameNode>\n}>\n\n/**\n * @internal\n */\nexport const CommonTableExpressionNameNode: CommonTableExpressionNameNodeFactory =\n  freeze<CommonTableExpressionNameNodeFactory>({\n    is(node): node is CommonTableExpressionNameNode {\n      return node.kind === 'CommonTableExpressionNameNode'\n    },\n\n    create(tableName, columnNames?) {\n      return freeze({\n        kind: 'CommonTableExpressionNameNode',\n        table: TableNode.create(tableName),\n        columns: columnNames\n          ? freeze(columnNames.map(ColumnNode.create))\n          : undefined,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/common-table-expression-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { CommonTableExpressionNameNode } from './common-table-expression-name-node.js'\nimport type { OperationNode } from './operation-node.js'\n\ntype CommonTableExpressionNodeProps = Pick<\n  CommonTableExpressionNode,\n  'materialized'\n>\n\nexport interface CommonTableExpressionNode extends OperationNode {\n  readonly kind: 'CommonTableExpressionNode'\n  readonly name: CommonTableExpressionNameNode\n  readonly materialized?: boolean\n  readonly expression: OperationNode\n}\n\ntype CommonTableExpressionNodeFactory = Readonly<{\n  is(node: OperationNode): node is CommonTableExpressionNode\n  create(\n    name: CommonTableExpressionNameNode,\n    expression: OperationNode,\n  ): Readonly<CommonTableExpressionNode>\n  cloneWith(\n    node: CommonTableExpressionNode,\n    props: CommonTableExpressionNodeProps,\n  ): Readonly<CommonTableExpressionNode>\n}>\n\n/**\n * @internal\n */\nexport const CommonTableExpressionNode: CommonTableExpressionNodeFactory =\n  freeze<CommonTableExpressionNodeFactory>({\n    is(node): node is CommonTableExpressionNode {\n      return node.kind === 'CommonTableExpressionNode'\n    },\n\n    create(name, expression) {\n      return freeze({\n        kind: 'CommonTableExpressionNode',\n        name,\n        expression,\n      })\n    },\n\n    cloneWith(node, props) {\n      return freeze({\n        ...node,\n        ...props,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/constraint-node.ts",
    "content": "import type { CheckConstraintNode } from './check-constraint-node.js'\nimport type { ForeignKeyConstraintNode } from './foreign-key-constraint-node.js'\nimport type { PrimaryKeyConstraintNode } from './primary-key-constraint-node.js'\nimport type { UniqueConstraintNode } from './unique-constraint-node.js'\n\nexport type ConstraintNode =\n  | PrimaryKeyConstraintNode\n  | UniqueConstraintNode\n  | CheckConstraintNode\n  | ForeignKeyConstraintNode\n"
  },
  {
    "path": "src/operation-node/create-index-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { RawNode } from './raw-node.js'\nimport type { TableNode } from './table-node.js'\nimport type { WhereNode } from './where-node.js'\n\nexport type CreateIndexNodeProps = Omit<CreateIndexNode, 'kind' | 'name'>\nexport type IndexType = 'btree' | 'hash' | 'gist' | 'gin'\n\nexport interface CreateIndexNode extends OperationNode {\n  readonly kind: 'CreateIndexNode'\n  // This isn't and shouldn't be a `SchemableIdentifier`. Postgres doesn't\n  // allow explicit schema for create index query. The schema is always the\n  // same as the target table's schema.\n  readonly name: IdentifierNode\n  readonly table?: TableNode\n  readonly columns?: OperationNode[]\n  readonly unique?: boolean\n  // TODO(samiko): Do we need to add an `IndexTypeNode` for consistency?\n  //               This would then be of type `IndexTypeNode | RawNode`.\n  readonly using?: RawNode\n  readonly ifNotExists?: boolean\n  readonly where?: WhereNode\n  readonly nullsNotDistinct?: boolean\n}\n\ntype CreateIndexNodeFactory = Readonly<{\n  is(node: OperationNode): node is CreateIndexNode\n  create(name: string): Readonly<CreateIndexNode>\n  cloneWith(\n    node: CreateIndexNode,\n    props: CreateIndexNodeProps,\n  ): Readonly<CreateIndexNode>\n  cloneWithColumns(\n    node: CreateIndexNode,\n    columns: OperationNode[],\n  ): Readonly<CreateIndexNode>\n}>\n\n/**\n * @internal\n */\nexport const CreateIndexNode: CreateIndexNodeFactory =\n  freeze<CreateIndexNodeFactory>({\n    is(node): node is CreateIndexNode {\n      return node.kind === 'CreateIndexNode'\n    },\n\n    create(name) {\n      return freeze({\n        kind: 'CreateIndexNode',\n        name: IdentifierNode.create(name),\n      })\n    },\n\n    cloneWith(node, props) {\n      return freeze({\n        ...node,\n        ...props,\n      })\n    },\n\n    cloneWithColumns(node, columns) {\n      return freeze({\n        ...node,\n        columns: [...(node.columns || []), ...columns],\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/create-schema-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport type CreateSchemaNodeParams = Omit<\n  Partial<CreateSchemaNode>,\n  'kind' | 'schema'\n>\n\nexport interface CreateSchemaNode extends OperationNode {\n  readonly kind: 'CreateSchemaNode'\n  readonly schema: IdentifierNode\n  readonly ifNotExists?: boolean\n}\n\ntype CreateSchemaNodeFactory = Readonly<{\n  is(node: OperationNode): node is CreateSchemaNode\n  create(\n    schema: string,\n    params?: CreateSchemaNodeParams,\n  ): Readonly<CreateSchemaNode>\n  cloneWith(\n    createSchema: CreateSchemaNode,\n    params: CreateSchemaNodeParams,\n  ): Readonly<CreateSchemaNode>\n}>\n\n/**\n * @internal\n */\nexport const CreateSchemaNode: CreateSchemaNodeFactory =\n  freeze<CreateSchemaNodeFactory>({\n    is(node): node is CreateSchemaNode {\n      return node.kind === 'CreateSchemaNode'\n    },\n\n    create(schema, params?) {\n      return freeze({\n        kind: 'CreateSchemaNode',\n        schema: IdentifierNode.create(schema),\n        ...params,\n      })\n    },\n\n    cloneWith(createSchema, params) {\n      return freeze({\n        ...createSchema,\n        ...params,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/create-table-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { TableNode } from './table-node.js'\nimport type { ConstraintNode } from './constraint-node.js'\nimport type { ColumnDefinitionNode } from './column-definition-node.js'\nimport type { ArrayItemType } from '../util/type-utils.js'\n\nexport const ON_COMMIT_ACTIONS = ['preserve rows', 'delete rows', 'drop']\nexport type OnCommitAction = ArrayItemType<typeof ON_COMMIT_ACTIONS>\n\nexport type CreateTableNodeParams = Omit<\n  CreateTableNode,\n  | 'kind'\n  | 'table'\n  | 'columns'\n  | 'constraints'\n  | 'frontModifiers'\n  | 'endModifiers'\n>\n\nexport interface CreateTableNode extends OperationNode {\n  readonly kind: 'CreateTableNode'\n  readonly table: TableNode\n  readonly columns: ReadonlyArray<ColumnDefinitionNode>\n  readonly constraints?: ReadonlyArray<ConstraintNode>\n  readonly temporary?: boolean\n  readonly ifNotExists?: boolean\n  readonly onCommit?: OnCommitAction\n  readonly frontModifiers?: ReadonlyArray<OperationNode>\n  readonly endModifiers?: ReadonlyArray<OperationNode>\n  readonly selectQuery?: OperationNode\n}\n\ntype CreateTableNodeFactory = Readonly<{\n  is(node: OperationNode): node is CreateTableNode\n  create(table: TableNode): Readonly<CreateTableNode>\n  cloneWithColumn(\n    createTable: CreateTableNode,\n    column: ColumnDefinitionNode,\n  ): Readonly<CreateTableNode>\n  cloneWithConstraint(\n    createTable: CreateTableNode,\n    constraint: ConstraintNode,\n  ): Readonly<CreateTableNode>\n  cloneWithFrontModifier(\n    createTable: CreateTableNode,\n    modifier: OperationNode,\n  ): Readonly<CreateTableNode>\n  cloneWithEndModifier(\n    createTable: CreateTableNode,\n    modifier: OperationNode,\n  ): Readonly<CreateTableNode>\n  cloneWith(\n    createTable: CreateTableNode,\n    params: CreateTableNodeParams,\n  ): Readonly<CreateTableNode>\n}>\n\n/**\n * @internal\n */\nexport const CreateTableNode: CreateTableNodeFactory =\n  freeze<CreateTableNodeFactory>({\n    is(node): node is CreateTableNode {\n      return node.kind === 'CreateTableNode'\n    },\n\n    create(table) {\n      return freeze({\n        kind: 'CreateTableNode',\n        table,\n        columns: freeze([]),\n      })\n    },\n\n    cloneWithColumn(createTable, column) {\n      return freeze({\n        ...createTable,\n        columns: freeze([...createTable.columns, column]),\n      })\n    },\n\n    cloneWithConstraint(createTable, constraint) {\n      return freeze({\n        ...createTable,\n        constraints: createTable.constraints\n          ? freeze([...createTable.constraints, constraint])\n          : freeze([constraint]),\n      })\n    },\n\n    cloneWithFrontModifier(createTable, modifier) {\n      return freeze({\n        ...createTable,\n        frontModifiers: createTable.frontModifiers\n          ? freeze([...createTable.frontModifiers, modifier])\n          : freeze([modifier]),\n      })\n    },\n\n    cloneWithEndModifier(createTable, modifier) {\n      return freeze({\n        ...createTable,\n        endModifiers: createTable.endModifiers\n          ? freeze([...createTable.endModifiers, modifier])\n          : freeze([modifier]),\n      })\n    },\n\n    cloneWith(createTable, params) {\n      return freeze({\n        ...createTable,\n        ...params,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/create-type-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { SchemableIdentifierNode } from './schemable-identifier-node.js'\nimport { ValueListNode } from './value-list-node.js'\nimport { ValueNode } from './value-node.js'\n\nexport type CreateTypeNodeParams = Omit<Partial<CreateTypeNode>, 'kind'>\n\nexport interface CreateTypeNode extends OperationNode {\n  readonly kind: 'CreateTypeNode'\n  readonly name: SchemableIdentifierNode\n  readonly enum?: ValueListNode\n}\n\ntype CreateTypeNodeFactory = Readonly<{\n  is(node: OperationNode): node is CreateTypeNode\n  create(name: SchemableIdentifierNode): Readonly<CreateTypeNode>\n  cloneWithEnum(\n    createType: CreateTypeNode,\n    values: readonly string[],\n  ): Readonly<CreateTypeNode>\n}>\n\n/**\n * @internal\n */\nexport const CreateTypeNode: CreateTypeNodeFactory =\n  freeze<CreateTypeNodeFactory>({\n    is(node): node is CreateTypeNode {\n      return node.kind === 'CreateTypeNode'\n    },\n\n    create(name) {\n      return freeze({\n        kind: 'CreateTypeNode',\n        name,\n      })\n    },\n\n    cloneWithEnum(createType, values) {\n      return freeze({\n        ...createType,\n        enum: ValueListNode.create(values.map(ValueNode.createImmediate)),\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/create-view-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { ColumnNode } from './column-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { RawNode } from './raw-node.js'\nimport { SchemableIdentifierNode } from './schemable-identifier-node.js'\nimport type { SelectQueryNode } from './select-query-node.js'\n\nexport type CreateViewNodeParams = Omit<\n  Partial<CreateViewNode>,\n  'kind' | 'name'\n>\n\nexport interface CreateViewNode extends OperationNode {\n  readonly kind: 'CreateViewNode'\n  readonly name: SchemableIdentifierNode\n  readonly temporary?: boolean\n  readonly materialized?: boolean\n  readonly orReplace?: boolean\n  readonly ifNotExists?: boolean\n  readonly columns?: ReadonlyArray<ColumnNode>\n  readonly as?: SelectQueryNode | RawNode\n}\n\ntype CreateViewNodeFactory = Readonly<{\n  is(node: OperationNode): node is CreateViewNode\n  create(name: string): Readonly<CreateViewNode>\n  cloneWith(\n    createView: CreateViewNode,\n    params: CreateViewNodeParams,\n  ): Readonly<CreateViewNode>\n}>\n\n/**\n * @internal\n */\nexport const CreateViewNode: CreateViewNodeFactory =\n  freeze<CreateViewNodeFactory>({\n    is(node): node is CreateViewNode {\n      return node.kind === 'CreateViewNode'\n    },\n\n    create(name) {\n      return freeze({\n        kind: 'CreateViewNode',\n        name: SchemableIdentifierNode.create(name),\n      })\n    },\n\n    cloneWith(createView, params) {\n      return freeze({\n        ...createView,\n        ...params,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/data-type-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nconst SIMPLE_COLUMN_DATA_TYPES = [\n  'varchar',\n  'char',\n  'text',\n  'integer',\n  'int2',\n  'int4',\n  'int8',\n  'smallint',\n  'bigint',\n  'boolean',\n  'real',\n  'double precision',\n  'float4',\n  'float8',\n  'decimal',\n  'numeric',\n  'binary',\n  'bytea',\n  'date',\n  'datetime',\n  'time',\n  'timetz',\n  'timestamp',\n  'timestamptz',\n  'serial',\n  'bigserial',\n  'uuid',\n  'json',\n  'jsonb',\n  'blob',\n  'varbinary',\n  'int4range',\n  'int4multirange',\n  'int8range',\n  'int8multirange',\n  'numrange',\n  'nummultirange',\n  'tsrange',\n  'tsmultirange',\n  'tstzrange',\n  'tstzmultirange',\n  'daterange',\n  'datemultirange',\n] as const\n\nconst COLUMN_DATA_TYPE_REGEX = [\n  /^varchar\\(\\d+\\)$/,\n  /^char\\(\\d+\\)$/,\n  /^decimal\\(\\d+, \\d+\\)$/,\n  /^numeric\\(\\d+, \\d+\\)$/,\n  /^binary\\(\\d+\\)$/,\n  /^datetime\\(\\d+\\)$/,\n  /^time\\(\\d+\\)$/,\n  /^timetz\\(\\d+\\)$/,\n  /^timestamp\\(\\d+\\)$/,\n  /^timestamptz\\(\\d+\\)$/,\n  /^varbinary\\(\\d+\\)$/,\n]\n\ntype SimpleColumnDataType = (typeof SIMPLE_COLUMN_DATA_TYPES)[number]\n\nexport type ColumnDataType =\n  | SimpleColumnDataType\n  | `varchar(${number})`\n  | `char(${number})`\n  | `decimal(${number}, ${number})`\n  | `numeric(${number}, ${number})`\n  | `binary(${number})`\n  | `datetime(${number})`\n  | `time(${number})`\n  | `timetz(${number})`\n  | `timestamp(${number})`\n  | `timestamptz(${number})`\n  | `varbinary(${number})`\n\nexport type DataTypeParams = Omit<DataTypeNode, 'kind' | 'dataType'>\n\nexport interface DataTypeNode extends OperationNode {\n  readonly kind: 'DataTypeNode'\n  readonly dataType: ColumnDataType\n}\n\ntype DataTypeNodeFactory = Readonly<{\n  is(node: OperationNode): node is DataTypeNode\n  create(dataType: ColumnDataType): Readonly<DataTypeNode>\n}>\n\n/**\n * @internal\n */\nexport const DataTypeNode: DataTypeNodeFactory = freeze<DataTypeNodeFactory>({\n  is(node): node is DataTypeNode {\n    return node.kind === 'DataTypeNode'\n  },\n\n  create(dataType) {\n    return freeze({\n      kind: 'DataTypeNode',\n      dataType,\n    })\n  },\n})\n\nexport function isColumnDataType(dataType: string): dataType is ColumnDataType {\n  if (SIMPLE_COLUMN_DATA_TYPES.includes(dataType as SimpleColumnDataType)) {\n    return true\n  }\n\n  if (COLUMN_DATA_TYPE_REGEX.some((r) => r.test(dataType))) {\n    return true\n  }\n\n  return false\n}\n"
  },
  {
    "path": "src/operation-node/default-insert-value-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface DefaultInsertValueNode extends OperationNode {\n  readonly kind: 'DefaultInsertValueNode'\n}\n\ntype DefaultInsertValueNodeFactory = Readonly<{\n  is(node: OperationNode): node is DefaultInsertValueNode\n  create(): Readonly<DefaultInsertValueNode>\n}>\n\n/**\n * @internal\n */\nexport const DefaultInsertValueNode: DefaultInsertValueNodeFactory =\n  freeze<DefaultInsertValueNodeFactory>({\n    is(node): node is DefaultInsertValueNode {\n      return node.kind === 'DefaultInsertValueNode'\n    },\n\n    create() {\n      return freeze({\n        kind: 'DefaultInsertValueNode',\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/default-value-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface DefaultValueNode extends OperationNode {\n  readonly kind: 'DefaultValueNode'\n  readonly defaultValue: OperationNode\n}\n\ntype DefaultValueNodeFactory = Readonly<{\n  is(node: OperationNode): node is DefaultValueNode\n  create(defaultValue: OperationNode): Readonly<DefaultValueNode>\n}>\n\n/**\n * @internal\n */\nexport const DefaultValueNode: DefaultValueNodeFactory =\n  freeze<DefaultValueNodeFactory>({\n    is(node): node is DefaultValueNode {\n      return node.kind === 'DefaultValueNode'\n    },\n\n    create(defaultValue) {\n      return freeze({\n        kind: 'DefaultValueNode',\n        defaultValue,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/delete-query-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { FromNode } from './from-node.js'\nimport type { JoinNode } from './join-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { ReturningNode } from './returning-node.js'\nimport type { WhereNode } from './where-node.js'\nimport type { WithNode } from './with-node.js'\nimport type { LimitNode } from './limit-node.js'\nimport type { OrderByNode } from './order-by-node.js'\nimport type { OrderByItemNode } from './order-by-item-node.js'\nimport type { ExplainNode } from './explain-node.js'\nimport { UsingNode } from './using-node.js'\nimport type { TopNode } from './top-node.js'\nimport type { OutputNode } from './output-node.js'\nimport { QueryNode } from './query-node.js'\n\nexport interface DeleteQueryNode extends OperationNode {\n  readonly kind: 'DeleteQueryNode'\n  readonly from: FromNode\n  readonly using?: UsingNode\n  readonly joins?: ReadonlyArray<JoinNode>\n  readonly where?: WhereNode\n  readonly returning?: ReturningNode\n  readonly with?: WithNode\n  readonly orderBy?: OrderByNode\n  readonly limit?: LimitNode\n  readonly explain?: ExplainNode\n  readonly endModifiers?: ReadonlyArray<OperationNode>\n  readonly top?: TopNode\n  readonly output?: OutputNode\n}\n\ntype DeleteQueryNodeFactory = Readonly<{\n  is(node: OperationNode): node is DeleteQueryNode\n  create(\n    fromItems: OperationNode[],\n    withNode?: WithNode,\n  ): Readonly<DeleteQueryNode>\n  cloneWithOrderByItems(\n    node: DeleteQueryNode,\n    items: ReadonlyArray<OrderByItemNode>,\n  ): Readonly<DeleteQueryNode>\n  cloneWithoutOrderBy(node: DeleteQueryNode): Readonly<DeleteQueryNode>\n  cloneWithLimit(\n    deleteNode: DeleteQueryNode,\n    limit: LimitNode,\n  ): Readonly<DeleteQueryNode>\n  cloneWithoutLimit(deleteNode: DeleteQueryNode): Readonly<DeleteQueryNode>\n  cloneWithUsing(\n    deleteNode: DeleteQueryNode,\n    tables: OperationNode[],\n  ): Readonly<DeleteQueryNode>\n}>\n\n/**\n * @internal\n */\nexport const DeleteQueryNode: DeleteQueryNodeFactory =\n  freeze<DeleteQueryNodeFactory>({\n    is(node): node is DeleteQueryNode {\n      return node.kind === 'DeleteQueryNode'\n    },\n\n    create(fromItems, withNode?) {\n      return freeze({\n        kind: 'DeleteQueryNode',\n        from: FromNode.create(fromItems),\n        ...(withNode && { with: withNode }),\n      })\n    },\n\n    // TODO: remove in v0.29\n    /**\n     * @deprecated Use `QueryNode.cloneWithoutOrderBy` instead.\n     */\n    cloneWithOrderByItems: (node, items) =>\n      QueryNode.cloneWithOrderByItems(node, items),\n\n    // TODO: remove in v0.29\n    /**\n     * @deprecated Use `QueryNode.cloneWithoutOrderBy` instead.\n     */\n    cloneWithoutOrderBy: (node) => QueryNode.cloneWithoutOrderBy(node),\n\n    cloneWithLimit(deleteNode, limit) {\n      return freeze({\n        ...deleteNode,\n        limit,\n      })\n    },\n\n    cloneWithoutLimit(deleteNode) {\n      return freeze({\n        ...deleteNode,\n        limit: undefined,\n      })\n    },\n\n    cloneWithUsing(deleteNode, tables) {\n      return freeze({\n        ...deleteNode,\n        using:\n          deleteNode.using !== undefined\n            ? UsingNode.cloneWithTables(deleteNode.using, tables)\n            : UsingNode.create(tables),\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/drop-column-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport { ColumnNode } from './column-node.js'\n\nexport interface DropColumnNode extends OperationNode {\n  readonly kind: 'DropColumnNode'\n  readonly column: ColumnNode\n}\n\ntype DropColumnNodeFactory = Readonly<{\n  is(node: OperationNode): node is DropColumnNode\n  create(column: string): Readonly<DropColumnNode>\n}>\n\n/**\n * @internal\n */\nexport const DropColumnNode: DropColumnNodeFactory =\n  freeze<DropColumnNodeFactory>({\n    is(node): node is DropColumnNode {\n      return node.kind === 'DropColumnNode'\n    },\n\n    create(column) {\n      return freeze({\n        kind: 'DropColumnNode',\n        column: ColumnNode.create(column),\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/drop-constraint-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\n\nexport type DropConstraintNodeProps = Omit<\n  DropConstraintNode,\n  'kind' | 'constraintName'\n>\n\nexport interface DropConstraintNode extends OperationNode {\n  readonly kind: 'DropConstraintNode'\n  readonly constraintName: IdentifierNode\n  readonly ifExists?: boolean\n  readonly modifier?: 'cascade' | 'restrict'\n}\n\ntype DropConstraintNodeFactory = Readonly<{\n  is(node: OperationNode): node is DropConstraintNode\n  create(\n    constraintName: string,\n    params?: DropConstraintNodeProps,\n  ): Readonly<DropConstraintNode>\n  cloneWith(\n    dropConstraint: DropConstraintNode,\n    props: DropConstraintNodeProps,\n  ): Readonly<DropConstraintNode>\n}>\n\n/**\n * @internal\n */\nexport const DropConstraintNode: DropConstraintNodeFactory =\n  freeze<DropConstraintNodeFactory>({\n    is(node): node is DropConstraintNode {\n      return node.kind === 'DropConstraintNode'\n    },\n\n    create(constraintName) {\n      return freeze({\n        kind: 'DropConstraintNode',\n        constraintName: IdentifierNode.create(constraintName),\n      })\n    },\n\n    cloneWith(dropConstraint, props) {\n      return freeze({\n        ...dropConstraint,\n        ...props,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/drop-index-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport { SchemableIdentifierNode } from './schemable-identifier-node.js'\nimport type { TableNode } from './table-node.js'\n\nexport type DropIndexNodeProps = Omit<DropIndexNode, 'kind' | 'name'>\n\nexport interface DropIndexNode extends OperationNode {\n  readonly kind: 'DropIndexNode'\n  readonly name: SchemableIdentifierNode\n  readonly table?: TableNode\n  readonly ifExists?: boolean\n  readonly cascade?: boolean\n}\n\ntype DropIndexNodeFactory = Readonly<{\n  is(node: OperationNode): node is DropIndexNode\n  create(name: string, params?: DropIndexNodeProps): Readonly<DropIndexNode>\n  cloneWith(\n    dropIndex: DropIndexNode,\n    props: DropIndexNodeProps,\n  ): Readonly<DropIndexNode>\n}>\n\n/**\n * @internal\n */\nexport const DropIndexNode: DropIndexNodeFactory = freeze<DropIndexNodeFactory>(\n  {\n    is(node): node is DropIndexNode {\n      return node.kind === 'DropIndexNode'\n    },\n\n    create(name, params?) {\n      return freeze({\n        kind: 'DropIndexNode',\n        name: SchemableIdentifierNode.create(name),\n        ...params,\n      })\n    },\n\n    cloneWith(dropIndex, props) {\n      return freeze({\n        ...dropIndex,\n        ...props,\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/operation-node/drop-schema-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport type DropSchemaNodeParams = Omit<\n  Partial<DropSchemaNode>,\n  'kind' | 'schema'\n>\n\nexport interface DropSchemaNode extends OperationNode {\n  readonly kind: 'DropSchemaNode'\n  readonly schema: IdentifierNode\n  readonly ifExists?: boolean\n  readonly cascade?: boolean\n}\n\ntype DropSchemaNodeFactory = Readonly<{\n  is(node: OperationNode): node is DropSchemaNode\n  create(\n    schema: string,\n    params?: DropSchemaNodeParams,\n  ): Readonly<DropSchemaNode>\n  cloneWith(\n    dropSchema: DropSchemaNode,\n    params: DropSchemaNodeParams,\n  ): Readonly<DropSchemaNode>\n}>\n\n/**\n * @internal\n */\nexport const DropSchemaNode: DropSchemaNodeFactory =\n  freeze<DropSchemaNodeFactory>({\n    is(node): node is DropSchemaNode {\n      return node.kind === 'DropSchemaNode'\n    },\n\n    create(schema, params?) {\n      return freeze({\n        kind: 'DropSchemaNode',\n        schema: IdentifierNode.create(schema),\n        ...params,\n      })\n    },\n\n    cloneWith(dropSchema, params) {\n      return freeze({\n        ...dropSchema,\n        ...params,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/drop-table-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { TableNode } from './table-node.js'\n\nexport type DropTablexNodeParams = Omit<\n  Partial<DropTableNode>,\n  'kind' | 'table'\n>\nexport interface DropTableNode extends OperationNode {\n  readonly kind: 'DropTableNode'\n  readonly table: TableNode\n  readonly ifExists?: boolean\n  readonly cascade?: boolean\n}\n\ntype DropTableNodeFactory = Readonly<{\n  is(node: OperationNode): node is DropTableNode\n  create(\n    table: TableNode,\n    params?: DropTablexNodeParams,\n  ): Readonly<DropTableNode>\n  cloneWith(\n    dropIndex: DropTableNode,\n    params: DropTablexNodeParams,\n  ): Readonly<DropTableNode>\n}>\n\n/**\n * @internal\n */\nexport const DropTableNode: DropTableNodeFactory = freeze<DropTableNodeFactory>(\n  {\n    is(node): node is DropTableNode {\n      return node.kind === 'DropTableNode'\n    },\n\n    create(table, params?) {\n      return freeze({\n        kind: 'DropTableNode',\n        table,\n        ...params,\n      })\n    },\n\n    cloneWith(dropIndex, params) {\n      return freeze({\n        ...dropIndex,\n        ...params,\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/operation-node/drop-type-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { SchemableIdentifierNode } from './schemable-identifier-node.js'\n\nexport type DropTypeNodeParams = Omit<Partial<DropTypeNode>, 'kind' | 'name'>\n\nexport interface DropTypeNode extends OperationNode {\n  readonly kind: 'DropTypeNode'\n  readonly name: SchemableIdentifierNode\n  readonly ifExists?: boolean\n}\n\ntype DropTypeNodeFactory = Readonly<{\n  is(node: OperationNode): node is DropTypeNode\n  create(name: SchemableIdentifierNode): Readonly<DropTypeNode>\n  cloneWith(\n    dropType: DropTypeNode,\n    params: DropTypeNodeParams,\n  ): Readonly<DropTypeNode>\n}>\n\n/**\n * @internal\n */\nexport const DropTypeNode: DropTypeNodeFactory = freeze<DropTypeNodeFactory>({\n  is(node): node is DropTypeNode {\n    return node.kind === 'DropTypeNode'\n  },\n\n  create(name) {\n    return freeze({\n      kind: 'DropTypeNode',\n      name,\n    })\n  },\n\n  cloneWith(dropType, params) {\n    return freeze({\n      ...dropType,\n      ...params,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/drop-view-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport { SchemableIdentifierNode } from './schemable-identifier-node.js'\n\nexport type DropViewNodeParams = Omit<Partial<DropViewNode>, 'kind' | 'name'>\n\nexport interface DropViewNode extends OperationNode {\n  readonly kind: 'DropViewNode'\n  readonly name: SchemableIdentifierNode\n  readonly ifExists?: boolean\n  readonly materialized?: boolean\n  readonly cascade?: boolean\n}\n\ntype DropViewNodeFactory = Readonly<{\n  is(node: OperationNode): node is DropViewNode\n  create(name: string): Readonly<DropViewNode>\n  cloneWith(\n    dropView: DropViewNode,\n    params: DropViewNodeParams,\n  ): Readonly<DropViewNode>\n}>\n\n/**\n * @internal\n */\nexport const DropViewNode: DropViewNodeFactory = freeze<DropViewNodeFactory>({\n  is(node): node is DropViewNode {\n    return node.kind === 'DropViewNode'\n  },\n\n  create(name) {\n    return freeze({\n      kind: 'DropViewNode',\n      name: SchemableIdentifierNode.create(name),\n    })\n  },\n\n  cloneWith(dropView, params) {\n    return freeze({\n      ...dropView,\n      ...params,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/explain-node.ts",
    "content": "import type { ExplainFormat } from '../util/explainable.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface ExplainNode extends OperationNode {\n  readonly kind: 'ExplainNode'\n  readonly format?: ExplainFormat\n  readonly options?: OperationNode\n}\n\ntype ExplainNodeFactory = Readonly<{\n  is(node: OperationNode): node is ExplainNode\n  create(format?: ExplainFormat, options?: OperationNode): Readonly<ExplainNode>\n}>\n\n/**\n * @internal\n */\nexport const ExplainNode: ExplainNodeFactory = freeze<ExplainNodeFactory>({\n  is(node): node is ExplainNode {\n    return node.kind === 'ExplainNode'\n  },\n\n  create(format?, options?) {\n    return freeze({\n      kind: 'ExplainNode',\n      format,\n      options,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/fetch-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport { ValueNode } from './value-node.js'\n\nexport type FetchModifier = 'only' | 'with ties'\n\nexport interface FetchNode extends OperationNode {\n  readonly kind: 'FetchNode'\n  readonly rowCount: ValueNode\n  readonly modifier: FetchModifier\n}\n\ntype FetchNodeFactory = Readonly<{\n  is(node: OperationNode): node is FetchNode\n  create(\n    rowCount: number | bigint,\n    modifier: FetchModifier,\n  ): Readonly<FetchNode>\n}>\n\n/**\n * @internal\n */\nexport const FetchNode: FetchNodeFactory = freeze<FetchNodeFactory>({\n  is(node): node is FetchNode {\n    return node.kind === 'FetchNode'\n  },\n\n  create(rowCount, modifier) {\n    return {\n      kind: 'FetchNode',\n      rowCount: ValueNode.create(rowCount),\n      modifier,\n    }\n  },\n})\n"
  },
  {
    "path": "src/operation-node/foreign-key-constraint-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { ColumnNode } from './column-node.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport {\n  type OnModifyForeignAction,\n  ReferencesNode,\n} from './references-node.js'\nimport type { TableNode } from './table-node.js'\n\nexport type ForeignKeyConstraintNodeProps = Omit<\n  ForeignKeyConstraintNode,\n  'kind' | 'columns' | 'references'\n>\n\nexport interface ForeignKeyConstraintNode extends OperationNode {\n  readonly kind: 'ForeignKeyConstraintNode'\n  readonly columns: ReadonlyArray<ColumnNode>\n  readonly references: ReferencesNode\n  readonly onDelete?: OnModifyForeignAction\n  readonly onUpdate?: OnModifyForeignAction\n  readonly name?: IdentifierNode\n  readonly deferrable?: boolean\n  readonly initiallyDeferred?: boolean\n}\n\ntype ForeignKeyConstraintNodeFactory = Readonly<{\n  is(node: OperationNode): node is ForeignKeyConstraintNode\n  create(\n    sourceColumns: ReadonlyArray<ColumnNode>,\n    targetTable: TableNode,\n    targetColumns: ReadonlyArray<ColumnNode>,\n    constraintName?: string,\n  ): Readonly<ForeignKeyConstraintNode>\n  cloneWith(\n    node: ForeignKeyConstraintNode,\n    props: ForeignKeyConstraintNodeProps,\n  ): Readonly<ForeignKeyConstraintNode>\n}>\n\n/**\n * @internal\n */\nexport const ForeignKeyConstraintNode: ForeignKeyConstraintNodeFactory =\n  freeze<ForeignKeyConstraintNodeFactory>({\n    is(node): node is ForeignKeyConstraintNode {\n      return node.kind === 'ForeignKeyConstraintNode'\n    },\n\n    create(sourceColumns, targetTable, targetColumns, constraintName?) {\n      return freeze({\n        kind: 'ForeignKeyConstraintNode',\n        columns: sourceColumns,\n        references: ReferencesNode.create(targetTable, targetColumns),\n        name: constraintName\n          ? IdentifierNode.create(constraintName)\n          : undefined,\n      })\n    },\n\n    cloneWith(node, props) {\n      return freeze({\n        ...node,\n        ...props,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/from-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface FromNode extends OperationNode {\n  readonly kind: 'FromNode'\n  readonly froms: ReadonlyArray<OperationNode>\n}\n\ntype FromNodeFactory = Readonly<{\n  is(node: OperationNode): node is FromNode\n  create(froms: ReadonlyArray<OperationNode>): Readonly<FromNode>\n  cloneWithFroms(\n    from: FromNode,\n    froms: ReadonlyArray<OperationNode>,\n  ): Readonly<FromNode>\n}>\n\n/**\n * @internal\n */\nexport const FromNode: FromNodeFactory = freeze<FromNodeFactory>({\n  is(node): node is FromNode {\n    return node.kind === 'FromNode'\n  },\n\n  create(froms) {\n    return freeze({\n      kind: 'FromNode',\n      froms: freeze(froms),\n    })\n  },\n\n  cloneWithFroms(from, froms) {\n    return freeze({\n      ...from,\n      froms: freeze([...from.froms, ...froms]),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/function-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface FunctionNode extends OperationNode {\n  readonly kind: 'FunctionNode'\n  readonly func: string\n  readonly arguments: ReadonlyArray<OperationNode>\n}\n\ntype FunctionNodeFactory = Readonly<{\n  is(node: OperationNode): node is FunctionNode\n  create(\n    func: string,\n    args: ReadonlyArray<OperationNode>,\n  ): Readonly<FunctionNode>\n}>\n\n/**\n * @internal\n */\nexport const FunctionNode: FunctionNodeFactory = freeze<FunctionNodeFactory>({\n  is(node): node is FunctionNode {\n    return node.kind === 'FunctionNode'\n  },\n\n  create(func, args) {\n    return freeze({\n      kind: 'FunctionNode',\n      func,\n      arguments: args,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/generated-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport type GeneratedNodeParams = Omit<GeneratedNode, 'kind' | 'expression'>\n\nexport interface GeneratedNode extends OperationNode {\n  readonly kind: 'GeneratedNode'\n  readonly byDefault?: boolean\n  readonly always?: boolean\n  readonly identity?: boolean\n  readonly stored?: boolean\n  readonly expression?: OperationNode\n}\n\ntype GeneratedNodeFactory = Readonly<{\n  is(node: OperationNode): node is GeneratedNode\n  create(params: GeneratedNodeParams): Readonly<GeneratedNode>\n  createWithExpression(expression: OperationNode): Readonly<GeneratedNode>\n  cloneWith(\n    node: GeneratedNode,\n    params: GeneratedNodeParams,\n  ): Readonly<GeneratedNode>\n}>\n\n/**\n * @internal\n */\nexport const GeneratedNode: GeneratedNodeFactory = freeze<GeneratedNodeFactory>(\n  {\n    is(node): node is GeneratedNode {\n      return node.kind === 'GeneratedNode'\n    },\n\n    create(params) {\n      return freeze({\n        kind: 'GeneratedNode',\n        ...params,\n      })\n    },\n\n    createWithExpression(expression) {\n      return freeze({\n        kind: 'GeneratedNode',\n        always: true,\n        expression,\n      })\n    },\n\n    cloneWith(node, params) {\n      return freeze({\n        ...node,\n        ...params,\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/operation-node/group-by-item-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface GroupByItemNode extends OperationNode {\n  readonly kind: 'GroupByItemNode'\n  readonly groupBy: OperationNode\n}\n\ntype GroupByItemNodeFactory = Readonly<{\n  is(node: OperationNode): node is GroupByItemNode\n  create(groupBy: OperationNode): Readonly<GroupByItemNode>\n}>\n\n/**\n * @internal\n */\nexport const GroupByItemNode: GroupByItemNodeFactory =\n  freeze<GroupByItemNodeFactory>({\n    is(node): node is GroupByItemNode {\n      return node.kind === 'GroupByItemNode'\n    },\n\n    create(groupBy) {\n      return freeze({\n        kind: 'GroupByItemNode',\n        groupBy,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/group-by-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { GroupByItemNode } from './group-by-item-node.js'\n\nexport interface GroupByNode extends OperationNode {\n  readonly kind: 'GroupByNode'\n  readonly items: ReadonlyArray<GroupByItemNode>\n}\n\ntype GroupByNodeFactory = Readonly<{\n  is(node: OperationNode): node is GroupByNode\n  create(items: ReadonlyArray<GroupByItemNode>): Readonly<GroupByNode>\n  cloneWithItems(\n    groupBy: GroupByNode,\n    items: ReadonlyArray<GroupByItemNode>,\n  ): Readonly<GroupByNode>\n}>\n\n/**\n * @internal\n */\nexport const GroupByNode: GroupByNodeFactory = freeze<GroupByNodeFactory>({\n  is(node): node is GroupByNode {\n    return node.kind === 'GroupByNode'\n  },\n\n  create(items) {\n    return freeze({\n      kind: 'GroupByNode',\n      items: freeze(items),\n    })\n  },\n\n  cloneWithItems(groupBy, items) {\n    return freeze({\n      ...groupBy,\n      items: freeze([...groupBy.items, ...items]),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/having-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { AndNode } from './and-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport { OrNode } from './or-node.js'\n\nexport interface HavingNode extends OperationNode {\n  readonly kind: 'HavingNode'\n  readonly having: OperationNode\n}\n\ntype HavingNodeFactory = Readonly<{\n  is(node: OperationNode): node is HavingNode\n  create(filter: OperationNode): Readonly<HavingNode>\n  cloneWithOperation(\n    havingNode: HavingNode,\n    operator: 'And' | 'Or',\n    operation: OperationNode,\n  ): Readonly<HavingNode>\n}>\n\n/**\n * @internal\n */\nexport const HavingNode: HavingNodeFactory = freeze<HavingNodeFactory>({\n  is(node): node is HavingNode {\n    return node.kind === 'HavingNode'\n  },\n\n  create(filter) {\n    return freeze({\n      kind: 'HavingNode',\n      having: filter,\n    })\n  },\n\n  cloneWithOperation(havingNode, operator, operation) {\n    return freeze({\n      ...havingNode,\n      having:\n        operator === 'And'\n          ? AndNode.create(havingNode.having, operation)\n          : OrNode.create(havingNode.having, operation),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/identifier-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface IdentifierNode extends OperationNode {\n  readonly kind: 'IdentifierNode'\n  readonly name: string\n}\n\ntype IdentifierNodeFactory = Readonly<{\n  is(node: OperationNode): node is IdentifierNode\n  create(name: string): Readonly<IdentifierNode>\n}>\n\n/**\n * @internal\n */\nexport const IdentifierNode: IdentifierNodeFactory =\n  freeze<IdentifierNodeFactory>({\n    is(node): node is IdentifierNode {\n      return node.kind === 'IdentifierNode'\n    },\n\n    create(name) {\n      return freeze({\n        kind: 'IdentifierNode',\n        name,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/insert-query-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { ColumnNode } from './column-node.js'\nimport type { ExplainNode } from './explain-node.js'\nimport type { OnConflictNode } from './on-conflict-node.js'\nimport type { OnDuplicateKeyNode } from './on-duplicate-key-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { OrActionNode } from './or-action-node.js'\nimport type { OutputNode } from './output-node.js'\nimport type { ReturningNode } from './returning-node.js'\nimport type { TableNode } from './table-node.js'\nimport type { TopNode } from './top-node.js'\nimport type { WithNode } from './with-node.js'\n\nexport type InsertQueryNodeProps = Omit<InsertQueryNode, 'kind' | 'into'>\n\nexport interface InsertQueryNode extends OperationNode {\n  readonly kind: 'InsertQueryNode'\n  readonly into?: TableNode\n  readonly columns?: ReadonlyArray<ColumnNode>\n  readonly values?: OperationNode\n  readonly returning?: ReturningNode\n  readonly onConflict?: OnConflictNode\n  readonly onDuplicateKey?: OnDuplicateKeyNode\n  readonly with?: WithNode\n  // TODO: remove in 0.29\n  /** @deprecated use {@link orAction} instead. */\n  readonly ignore?: boolean\n  readonly orAction?: OrActionNode\n  readonly replace?: boolean\n  readonly explain?: ExplainNode\n  readonly defaultValues?: boolean\n  readonly endModifiers?: ReadonlyArray<OperationNode>\n  readonly top?: TopNode\n  readonly output?: OutputNode\n}\n\ntype InsertQueryNodeFactory = Readonly<{\n  is(node: OperationNode): node is InsertQueryNode\n  create(\n    into: TableNode,\n    withNode?: WithNode,\n    replace?: boolean,\n  ): Readonly<InsertQueryNode>\n  createWithoutInto(): Readonly<InsertQueryNode>\n  cloneWith(\n    insertQuery: InsertQueryNode,\n    props: InsertQueryNodeProps,\n  ): Readonly<InsertQueryNode>\n}>\n\n/**\n * @internal\n */\nexport const InsertQueryNode: InsertQueryNodeFactory =\n  freeze<InsertQueryNodeFactory>({\n    is(node): node is InsertQueryNode {\n      return node.kind === 'InsertQueryNode'\n    },\n\n    create(into, withNode?, replace?) {\n      return freeze({\n        kind: 'InsertQueryNode',\n        into,\n        ...(withNode && { with: withNode }),\n        replace,\n      })\n    },\n\n    createWithoutInto() {\n      return freeze({\n        kind: 'InsertQueryNode',\n      })\n    },\n\n    cloneWith(insertQuery, props) {\n      return freeze({\n        ...insertQuery,\n        ...props,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/join-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { OnNode } from './on-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport type JoinType =\n  | 'InnerJoin'\n  | 'LeftJoin'\n  | 'RightJoin'\n  | 'FullJoin'\n  | 'CrossJoin'\n  | 'LateralInnerJoin'\n  | 'LateralLeftJoin'\n  | 'LateralCrossJoin'\n  | 'Using'\n  | 'OuterApply'\n  | 'CrossApply'\n\nexport interface JoinNode extends OperationNode {\n  readonly kind: 'JoinNode'\n  readonly joinType: JoinType\n  readonly table: OperationNode\n  readonly on?: OnNode\n}\n\ntype JoinNodeFactory = Readonly<{\n  is(node: OperationNode): node is JoinNode\n  create(joinType: JoinType, table: OperationNode): Readonly<JoinNode>\n  createWithOn(\n    joinType: JoinType,\n    table: OperationNode,\n    on: OperationNode,\n  ): Readonly<JoinNode>\n  cloneWithOn(joinNode: JoinNode, operation: OperationNode): Readonly<JoinNode>\n}>\n\n/**\n * @internal\n */\nexport const JoinNode: JoinNodeFactory = freeze<JoinNodeFactory>({\n  is(node): node is JoinNode {\n    return node.kind === 'JoinNode'\n  },\n\n  create(joinType, table) {\n    return freeze({\n      kind: 'JoinNode',\n      joinType,\n      table,\n      on: undefined,\n    })\n  },\n\n  createWithOn(joinType, table, on) {\n    return freeze({\n      kind: 'JoinNode',\n      joinType,\n      table,\n      on: OnNode.create(on),\n    })\n  },\n\n  cloneWithOn(joinNode, operation) {\n    return freeze({\n      ...joinNode,\n      on: joinNode.on\n        ? OnNode.cloneWithOperation(joinNode.on, 'And', operation)\n        : OnNode.create(operation),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/json-operator-chain-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { OperatorNode } from './operator-node.js'\nimport type { ValueNode } from './value-node.js'\n\nexport interface JSONOperatorChainNode extends OperationNode {\n  readonly kind: 'JSONOperatorChainNode'\n  readonly operator: OperatorNode\n  readonly values: readonly ValueNode[]\n}\n\ntype JSONOperatorChainNodeFactory = Readonly<{\n  is(node: OperationNode): node is JSONOperatorChainNode\n  create(operator: OperatorNode): Readonly<JSONOperatorChainNode>\n  cloneWithValue(\n    node: JSONOperatorChainNode,\n    value: ValueNode,\n  ): Readonly<JSONOperatorChainNode>\n}>\n\n/**\n * @internal\n */\nexport const JSONOperatorChainNode: JSONOperatorChainNodeFactory =\n  freeze<JSONOperatorChainNodeFactory>({\n    is(node): node is JSONOperatorChainNode {\n      return node.kind === 'JSONOperatorChainNode'\n    },\n\n    create(operator) {\n      return freeze({\n        kind: 'JSONOperatorChainNode',\n        operator,\n        values: freeze([]),\n      })\n    },\n\n    cloneWithValue(node, value) {\n      return freeze({\n        ...node,\n        values: freeze([...node.values, value]),\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/json-path-leg-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport type JSONPathLegType = 'Member' | 'ArrayLocation'\n\nexport interface JSONPathLegNode extends OperationNode {\n  readonly kind: 'JSONPathLegNode'\n  readonly type: JSONPathLegType\n  readonly value: string | number\n}\n\ntype JSONPathLegNodeFactory = Readonly<{\n  is(node: OperationNode): node is JSONPathLegNode\n  create(\n    type: JSONPathLegType,\n    value: string | number,\n  ): Readonly<JSONPathLegNode>\n}>\n\n/**\n * @internal\n */\nexport const JSONPathLegNode: JSONPathLegNodeFactory =\n  freeze<JSONPathLegNodeFactory>({\n    is(node): node is JSONPathLegNode {\n      return node.kind === 'JSONPathLegNode'\n    },\n\n    create(type, value) {\n      return freeze({\n        kind: 'JSONPathLegNode',\n        type,\n        value,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/json-path-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { JSONPathLegNode } from './json-path-leg-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { OperatorNode } from './operator-node.js'\n\nexport interface JSONPathNode extends OperationNode {\n  readonly kind: 'JSONPathNode'\n  readonly inOperator?: OperatorNode\n  readonly pathLegs: ReadonlyArray<JSONPathLegNode>\n}\n\ntype JSONPathNodeFactory = Readonly<{\n  is(node: OperationNode): node is JSONPathNode\n  create(inOperator?: OperatorNode): Readonly<JSONPathNode>\n  cloneWithLeg(\n    jsonPathNode: JSONPathNode,\n    pathLeg: JSONPathLegNode,\n  ): Readonly<JSONPathNode>\n}>\n\n/**\n * @internal\n */\nexport const JSONPathNode: JSONPathNodeFactory = freeze<JSONPathNodeFactory>({\n  is(node): node is JSONPathNode {\n    return node.kind === 'JSONPathNode'\n  },\n\n  create(inOperator?) {\n    return freeze({\n      kind: 'JSONPathNode',\n      inOperator,\n      pathLegs: freeze([]),\n    })\n  },\n\n  cloneWithLeg(jsonPathNode, pathLeg) {\n    return freeze({\n      ...jsonPathNode,\n      pathLegs: freeze([...jsonPathNode.pathLegs, pathLeg]),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/json-reference-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { JSONOperatorChainNode } from './json-operator-chain-node.js'\nimport type { JSONPathNode } from './json-path-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { ReferenceNode } from './reference-node.js'\n\nexport interface JSONReferenceNode extends OperationNode {\n  readonly kind: 'JSONReferenceNode'\n  readonly reference: ReferenceNode\n  readonly traversal: JSONPathNode | JSONOperatorChainNode\n}\n\ntype JSONReferenceNodeFactory = Readonly<{\n  is(node: OperationNode): node is JSONReferenceNode\n  create(\n    reference: ReferenceNode,\n    traversal: JSONPathNode | JSONOperatorChainNode,\n  ): Readonly<JSONReferenceNode>\n  cloneWithTraversal(\n    node: JSONReferenceNode,\n    traversal: JSONPathNode | JSONOperatorChainNode,\n  ): Readonly<JSONReferenceNode>\n}>\n\n/**\n * @internal\n */\nexport const JSONReferenceNode: JSONReferenceNodeFactory =\n  freeze<JSONReferenceNodeFactory>({\n    is(node): node is JSONReferenceNode {\n      return node.kind === 'JSONReferenceNode'\n    },\n\n    create(reference, traversal) {\n      return freeze({\n        kind: 'JSONReferenceNode',\n        reference,\n        traversal,\n      })\n    },\n\n    cloneWithTraversal(node, traversal) {\n      return freeze({\n        ...node,\n        traversal,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/limit-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface LimitNode extends OperationNode {\n  readonly kind: 'LimitNode'\n  readonly limit: OperationNode\n}\n\ntype LimitNodeFactory = Readonly<{\n  is(node: OperationNode): node is LimitNode\n  create(limit: OperationNode): Readonly<LimitNode>\n}>\n\n/**\n * @internal\n */\nexport const LimitNode: LimitNodeFactory = freeze<LimitNodeFactory>({\n  is(node): node is LimitNode {\n    return node.kind === 'LimitNode'\n  },\n\n  create(limit) {\n    return freeze({\n      kind: 'LimitNode',\n      limit,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/list-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface ListNode extends OperationNode {\n  readonly kind: 'ListNode'\n  readonly items: ReadonlyArray<OperationNode>\n}\n\ntype ListNodeFactory = Readonly<{\n  is(node: OperationNode): node is ListNode\n  create(items: ReadonlyArray<OperationNode>): Readonly<ListNode>\n}>\n\n/**\n * @internal\n */\nexport const ListNode: ListNodeFactory = freeze<ListNodeFactory>({\n  is(node): node is ListNode {\n    return node.kind === 'ListNode'\n  },\n\n  create(items) {\n    return freeze({\n      kind: 'ListNode',\n      items: freeze(items),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/matched-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface MatchedNode extends OperationNode {\n  readonly kind: 'MatchedNode'\n  readonly not: boolean\n  readonly bySource: boolean\n}\n\ntype MatchedNodeFactory = Readonly<{\n  is(node: OperationNode): node is MatchedNode\n  create(not: boolean, bySource?: boolean): Readonly<MatchedNode>\n}>\n\n/**\n * @internal\n */\nexport const MatchedNode: MatchedNodeFactory = freeze<MatchedNodeFactory>({\n  is(node): node is MatchedNode {\n    return node.kind === 'MatchedNode'\n  },\n\n  create(not, bySource = false) {\n    return freeze({\n      kind: 'MatchedNode',\n      not,\n      bySource,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/merge-query-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { AliasNode } from './alias-node.js'\nimport type { JoinNode } from './join-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { OutputNode } from './output-node.js'\nimport type { ReturningNode } from './returning-node.js'\nimport type { TableNode } from './table-node.js'\nimport type { TopNode } from './top-node.js'\nimport { WhenNode } from './when-node.js'\nimport type { WithNode } from './with-node.js'\n\nexport interface MergeQueryNode extends OperationNode {\n  readonly kind: 'MergeQueryNode'\n  readonly into: TableNode | AliasNode\n  readonly using?: JoinNode\n  readonly whens?: ReadonlyArray<WhenNode>\n  readonly with?: WithNode\n  readonly top?: TopNode\n  readonly returning?: ReturningNode\n  readonly output?: OutputNode\n  readonly endModifiers?: ReadonlyArray<OperationNode>\n}\n\ntype MergeQueryNodeFactory = Readonly<{\n  is(node: OperationNode): node is MergeQueryNode\n  create(\n    into: TableNode | AliasNode,\n    withNode?: WithNode,\n  ): Readonly<MergeQueryNode>\n  cloneWithUsing(\n    mergeNode: MergeQueryNode,\n    using: JoinNode,\n  ): Readonly<MergeQueryNode>\n  cloneWithWhen(\n    mergeNode: MergeQueryNode,\n    when: WhenNode,\n  ): Readonly<MergeQueryNode>\n  cloneWithThen(\n    mergeNode: MergeQueryNode,\n    then: OperationNode,\n  ): Readonly<MergeQueryNode>\n}>\n\n/**\n * @internal\n */\nexport const MergeQueryNode: MergeQueryNodeFactory =\n  freeze<MergeQueryNodeFactory>({\n    is(node): node is MergeQueryNode {\n      return node.kind === 'MergeQueryNode'\n    },\n\n    create(into, withNode?) {\n      return freeze({\n        kind: 'MergeQueryNode',\n        into,\n        ...(withNode && { with: withNode }),\n      })\n    },\n\n    cloneWithUsing(mergeNode, using) {\n      return freeze({\n        ...mergeNode,\n        using,\n      })\n    },\n\n    cloneWithWhen(mergeNode, when) {\n      return freeze({\n        ...mergeNode,\n        whens: mergeNode.whens\n          ? freeze([...mergeNode.whens, when])\n          : freeze([when]),\n      })\n    },\n\n    cloneWithThen(mergeNode, then) {\n      return freeze({\n        ...mergeNode,\n        whens: mergeNode.whens\n          ? freeze([\n              ...mergeNode.whens.slice(0, -1),\n              WhenNode.cloneWithResult(\n                mergeNode.whens[mergeNode.whens.length - 1],\n                then,\n              ),\n            ])\n          : undefined,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/modify-column-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { ColumnDefinitionNode } from './column-definition-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface ModifyColumnNode extends OperationNode {\n  readonly kind: 'ModifyColumnNode'\n  readonly column: ColumnDefinitionNode\n}\n\ntype ModifyColumnNodeFactory = Readonly<{\n  is(node: OperationNode): node is ModifyColumnNode\n  create(column: ColumnDefinitionNode): Readonly<ModifyColumnNode>\n}>\n\n/**\n * @internal\n */\nexport const ModifyColumnNode: ModifyColumnNodeFactory =\n  freeze<ModifyColumnNodeFactory>({\n    is(node): node is ModifyColumnNode {\n      return node.kind === 'ModifyColumnNode'\n    },\n\n    create(column) {\n      return freeze({\n        kind: 'ModifyColumnNode',\n        column,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/offset-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface OffsetNode extends OperationNode {\n  readonly kind: 'OffsetNode'\n  readonly offset: OperationNode\n}\n\ntype OffsetNodeFactory = Readonly<{\n  is(node: OperationNode): node is OffsetNode\n  create(offset: OperationNode): Readonly<OffsetNode>\n}>\n\n/**\n * @internal\n */\nexport const OffsetNode: OffsetNodeFactory = freeze<OffsetNodeFactory>({\n  is(node): node is OffsetNode {\n    return node.kind === 'OffsetNode'\n  },\n\n  create(offset) {\n    return freeze({\n      kind: 'OffsetNode',\n      offset,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/on-conflict-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { ColumnNode } from './column-node.js'\nimport type { ColumnUpdateNode } from './column-update-node.js'\nimport type { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport { WhereNode } from './where-node.js'\n\nexport type OnConflictNodeProps = Omit<\n  OnConflictNode,\n  'kind' | 'indexWhere' | 'updateWhere'\n>\n\nexport interface OnConflictNode extends OperationNode {\n  readonly kind: 'OnConflictNode'\n  readonly columns?: ReadonlyArray<ColumnNode>\n  readonly constraint?: IdentifierNode\n  readonly indexExpression?: OperationNode\n  readonly indexWhere?: WhereNode\n  readonly updates?: ReadonlyArray<ColumnUpdateNode>\n  readonly updateWhere?: WhereNode\n  readonly doNothing?: boolean\n}\n\ntype OnConflictNodeFactory = Readonly<{\n  is(node: OperationNode): node is OnConflictNode\n  create(): Readonly<OnConflictNode>\n  cloneWith(\n    node: OnConflictNode,\n    props: OnConflictNodeProps,\n  ): Readonly<OnConflictNode>\n  cloneWithIndexWhere(\n    node: OnConflictNode,\n    operation: OperationNode,\n  ): Readonly<OnConflictNode>\n  cloneWithIndexOrWhere(\n    node: OnConflictNode,\n    operation: OperationNode,\n  ): Readonly<OnConflictNode>\n  cloneWithUpdateWhere(\n    node: OnConflictNode,\n    operation: OperationNode,\n  ): Readonly<OnConflictNode>\n  cloneWithUpdateOrWhere(\n    node: OnConflictNode,\n    operation: OperationNode,\n  ): Readonly<OnConflictNode>\n  cloneWithoutIndexWhere(node: OnConflictNode): Readonly<OnConflictNode>\n  cloneWithoutUpdateWhere(node: OnConflictNode): Readonly<OnConflictNode>\n}>\n/**\n * @internal\n */\nexport const OnConflictNode: OnConflictNodeFactory =\n  freeze<OnConflictNodeFactory>({\n    is(node): node is OnConflictNode {\n      return node.kind === 'OnConflictNode'\n    },\n\n    create() {\n      return freeze({\n        kind: 'OnConflictNode',\n      })\n    },\n\n    cloneWith(node, props) {\n      return freeze({\n        ...node,\n        ...props,\n      })\n    },\n\n    cloneWithIndexWhere(node, operation) {\n      return freeze({\n        ...node,\n        indexWhere: node.indexWhere\n          ? WhereNode.cloneWithOperation(node.indexWhere, 'And', operation)\n          : WhereNode.create(operation),\n      })\n    },\n\n    cloneWithIndexOrWhere(node, operation) {\n      return freeze({\n        ...node,\n        indexWhere: node.indexWhere\n          ? WhereNode.cloneWithOperation(node.indexWhere, 'Or', operation)\n          : WhereNode.create(operation),\n      })\n    },\n\n    cloneWithUpdateWhere(node, operation) {\n      return freeze({\n        ...node,\n        updateWhere: node.updateWhere\n          ? WhereNode.cloneWithOperation(node.updateWhere, 'And', operation)\n          : WhereNode.create(operation),\n      })\n    },\n\n    cloneWithUpdateOrWhere(node, operation) {\n      return freeze({\n        ...node,\n        updateWhere: node.updateWhere\n          ? WhereNode.cloneWithOperation(node.updateWhere, 'Or', operation)\n          : WhereNode.create(operation),\n      })\n    },\n\n    cloneWithoutIndexWhere(node) {\n      return freeze({\n        ...node,\n        indexWhere: undefined,\n      })\n    },\n\n    cloneWithoutUpdateWhere(node) {\n      return freeze({\n        ...node,\n        updateWhere: undefined,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/on-duplicate-key-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { ColumnUpdateNode } from './column-update-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport type OnDuplicateKeyNodeProps = Omit<OnDuplicateKeyNode, 'kind'>\n\nexport interface OnDuplicateKeyNode extends OperationNode {\n  readonly kind: 'OnDuplicateKeyNode'\n  readonly updates: ReadonlyArray<ColumnUpdateNode>\n}\n\ntype OnDuplicateKeyNodeFactory = Readonly<{\n  is(node: OperationNode): node is OnDuplicateKeyNode\n  create(updates: ReadonlyArray<ColumnUpdateNode>): Readonly<OnDuplicateKeyNode>\n}>\n\n/**\n * @internal\n */\nexport const OnDuplicateKeyNode: OnDuplicateKeyNodeFactory =\n  freeze<OnDuplicateKeyNodeFactory>({\n    is(node): node is OnDuplicateKeyNode {\n      return node.kind === 'OnDuplicateKeyNode'\n    },\n\n    create(updates) {\n      return freeze({\n        kind: 'OnDuplicateKeyNode',\n        updates,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/on-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { AndNode } from './and-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport { OrNode } from './or-node.js'\n\nexport interface OnNode extends OperationNode {\n  readonly kind: 'OnNode'\n  readonly on: OperationNode\n}\n\ntype OnNodeFactory = Readonly<{\n  is(node: OperationNode): node is OnNode\n  create(filter: OperationNode): Readonly<OnNode>\n  cloneWithOperation(\n    onNode: OnNode,\n    operator: 'And' | 'Or',\n    operation: OperationNode,\n  ): Readonly<OnNode>\n}>\n\n/**\n * @internal\n */\nexport const OnNode: OnNodeFactory = freeze<OnNodeFactory>({\n  is(node): node is OnNode {\n    return node.kind === 'OnNode'\n  },\n\n  create(filter) {\n    return freeze({\n      kind: 'OnNode',\n      on: filter,\n    })\n  },\n\n  cloneWithOperation(onNode, operator, operation) {\n    return freeze({\n      ...onNode,\n      on:\n        operator === 'And'\n          ? AndNode.create(onNode.on, operation)\n          : OrNode.create(onNode.on, operation),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/operation-node-source.ts",
    "content": "import { isFunction, isObject } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface OperationNodeSource {\n  toOperationNode(): OperationNode\n}\n\nexport function isOperationNodeSource(\n  obj: unknown,\n): obj is OperationNodeSource {\n  return isObject(obj) && isFunction(obj.toOperationNode)\n}\n"
  },
  {
    "path": "src/operation-node/operation-node-transformer.ts",
    "content": "import type { AliasNode } from './alias-node.js'\nimport type { ColumnNode } from './column-node.js'\nimport type { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode, OperationNodeKind } from './operation-node.js'\nimport type { ReferenceNode } from './reference-node.js'\nimport type { SelectAllNode } from './select-all-node.js'\nimport type { SelectionNode } from './selection-node.js'\nimport type { TableNode } from './table-node.js'\nimport type { AndNode } from './and-node.js'\nimport type { JoinNode } from './join-node.js'\nimport type { OrNode } from './or-node.js'\nimport type { ParensNode } from './parens-node.js'\nimport type { PrimitiveValueListNode } from './primitive-value-list-node.js'\nimport type { RawNode } from './raw-node.js'\nimport type { SelectQueryNode } from './select-query-node.js'\nimport type { ValueListNode } from './value-list-node.js'\nimport type { ValueNode } from './value-node.js'\nimport type { OperatorNode } from './operator-node.js'\nimport type { FromNode } from './from-node.js'\nimport type { WhereNode } from './where-node.js'\nimport type { InsertQueryNode } from './insert-query-node.js'\nimport type { DeleteQueryNode } from './delete-query-node.js'\nimport type { ReturningNode } from './returning-node.js'\nimport type { CreateTableNode } from './create-table-node.js'\nimport type { AddColumnNode } from './add-column-node.js'\nimport type { DropTableNode } from './drop-table-node.js'\nimport type { DataTypeNode } from './data-type-node.js'\nimport type { OrderByNode } from './order-by-node.js'\nimport type { OrderByItemNode } from './order-by-item-node.js'\nimport type { GroupByNode } from './group-by-node.js'\nimport type { GroupByItemNode } from './group-by-item-node.js'\nimport type { UpdateQueryNode } from './update-query-node.js'\nimport type { ColumnUpdateNode } from './column-update-node.js'\nimport type { LimitNode } from './limit-node.js'\nimport type { OffsetNode } from './offset-node.js'\nimport type { OnConflictNode } from './on-conflict-node.js'\nimport type { CreateIndexNode } from './create-index-node.js'\nimport type { ListNode } from './list-node.js'\nimport type { DropIndexNode } from './drop-index-node.js'\nimport type { PrimaryKeyConstraintNode } from './primary-key-constraint-node.js'\nimport type { UniqueConstraintNode } from './unique-constraint-node.js'\nimport type { ReferencesNode } from './references-node.js'\nimport type { CheckConstraintNode } from './check-constraint-node.js'\nimport type { WithNode } from './with-node.js'\nimport type { CommonTableExpressionNode } from './common-table-expression-node.js'\nimport type { CommonTableExpressionNameNode } from './common-table-expression-name-node.js'\nimport type { HavingNode } from './having-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport { requireAllProps } from '../util/require-all-props.js'\nimport type { CreateSchemaNode } from './create-schema-node.js'\nimport type { DropSchemaNode } from './drop-schema-node.js'\nimport type { AlterTableNode } from './alter-table-node.js'\nimport type { DropColumnNode } from './drop-column-node.js'\nimport type { RenameColumnNode } from './rename-column-node.js'\nimport type { AlterColumnNode } from './alter-column-node.js'\nimport type { AddConstraintNode } from './add-constraint-node.js'\nimport type { DropConstraintNode } from './drop-constraint-node.js'\nimport type { ForeignKeyConstraintNode } from './foreign-key-constraint-node.js'\nimport type { ColumnDefinitionNode } from './column-definition-node.js'\nimport type { ModifyColumnNode } from './modify-column-node.js'\nimport type { OnDuplicateKeyNode } from './on-duplicate-key-node.js'\nimport type { CreateViewNode } from './create-view-node.js'\nimport type { DropViewNode } from './drop-view-node.js'\nimport type { GeneratedNode } from './generated-node.js'\nimport type { DefaultValueNode } from './default-value-node.js'\nimport type { OnNode } from './on-node.js'\nimport type { ValuesNode } from './values-node.js'\nimport type { SelectModifierNode } from './select-modifier-node.js'\nimport type { CreateTypeNode } from './create-type-node.js'\nimport type { DropTypeNode } from './drop-type-node.js'\nimport type { ExplainNode } from './explain-node.js'\nimport type { SchemableIdentifierNode } from './schemable-identifier-node.js'\nimport type { DefaultInsertValueNode } from './default-insert-value-node.js'\nimport type { AggregateFunctionNode } from './aggregate-function-node.js'\nimport type { OverNode } from './over-node.js'\nimport type { PartitionByNode } from './partition-by-node.js'\nimport type { PartitionByItemNode } from './partition-by-item-node.js'\nimport type { SetOperationNode } from './set-operation-node.js'\nimport type { BinaryOperationNode } from './binary-operation-node.js'\nimport type { UnaryOperationNode } from './unary-operation-node.js'\nimport type { UsingNode } from './using-node.js'\nimport type { FunctionNode } from './function-node.js'\nimport type { CaseNode } from './case-node.js'\nimport type { WhenNode } from './when-node.js'\nimport type { JSONReferenceNode } from './json-reference-node.js'\nimport type { JSONPathNode } from './json-path-node.js'\nimport type { JSONPathLegNode } from './json-path-leg-node.js'\nimport type { JSONOperatorChainNode } from './json-operator-chain-node.js'\nimport type { TupleNode } from './tuple-node.js'\nimport type { MergeQueryNode } from './merge-query-node.js'\nimport type { MatchedNode } from './matched-node.js'\nimport type { AddIndexNode } from './add-index-node.js'\nimport type { CastNode } from './cast-node.js'\nimport type { FetchNode } from './fetch-node.js'\nimport type { TopNode } from './top-node.js'\nimport type { OutputNode } from './output-node.js'\nimport type { RefreshMaterializedViewNode } from './refresh-materialized-view-node.js'\nimport type { OrActionNode } from './or-action-node.js'\nimport type { CollateNode } from './collate-node.js'\nimport type { QueryId } from '../util/query-id.js'\nimport type { RenameConstraintNode } from './rename-constraint-node.js'\n\n/**\n * Transforms an operation node tree into another one.\n *\n * Kysely queries are expressed internally as a tree of objects (operation nodes).\n * `OperationNodeTransformer` takes such a tree as its input and returns a\n * transformed deep copy of it. By default the `OperationNodeTransformer`\n * does nothing. You need to override one or more methods to make it do\n * something.\n *\n * There's a method for each node type. For example if you'd like to convert\n * each identifier (table name, column name, alias etc.) from camelCase to\n * snake_case, you'd do something like this:\n *\n * ```ts\n * import { type IdentifierNode, OperationNodeTransformer } from 'kysely'\n * import snakeCase from 'lodash/snakeCase'\n *\n * class CamelCaseTransformer extends OperationNodeTransformer {\n *   override transformIdentifier(node: IdentifierNode): IdentifierNode {\n *     node = super.transformIdentifier(node)\n *\n *     return {\n *       ...node,\n *       name: snakeCase(node.name),\n *     }\n *   }\n * }\n *\n * const transformer = new CamelCaseTransformer()\n *\n * const query = db.selectFrom('person').select(['first_name', 'last_name'])\n *\n * const tree = transformer.transformNode(query.toOperationNode())\n * ```\n */\nexport class OperationNodeTransformer {\n  protected readonly nodeStack: OperationNode[] = []\n\n  readonly #transformers: Record<\n    OperationNodeKind,\n    // TODO: make `queryId` required in v0.29 ?\n    (node: any, queryId?: QueryId) => any\n  > = freeze({\n    AliasNode: this.transformAlias.bind(this),\n    ColumnNode: this.transformColumn.bind(this),\n    IdentifierNode: this.transformIdentifier.bind(this),\n    SchemableIdentifierNode: this.transformSchemableIdentifier.bind(this),\n    RawNode: this.transformRaw.bind(this),\n    ReferenceNode: this.transformReference.bind(this),\n    SelectQueryNode: this.transformSelectQuery.bind(this),\n    SelectionNode: this.transformSelection.bind(this),\n    TableNode: this.transformTable.bind(this),\n    FromNode: this.transformFrom.bind(this),\n    SelectAllNode: this.transformSelectAll.bind(this),\n    AndNode: this.transformAnd.bind(this),\n    OrNode: this.transformOr.bind(this),\n    ValueNode: this.transformValue.bind(this),\n    ValueListNode: this.transformValueList.bind(this),\n    PrimitiveValueListNode: this.transformPrimitiveValueList.bind(this),\n    ParensNode: this.transformParens.bind(this),\n    JoinNode: this.transformJoin.bind(this),\n    OperatorNode: this.transformOperator.bind(this),\n    WhereNode: this.transformWhere.bind(this),\n    InsertQueryNode: this.transformInsertQuery.bind(this),\n    DeleteQueryNode: this.transformDeleteQuery.bind(this),\n    ReturningNode: this.transformReturning.bind(this),\n    CreateTableNode: this.transformCreateTable.bind(this),\n    AddColumnNode: this.transformAddColumn.bind(this),\n    ColumnDefinitionNode: this.transformColumnDefinition.bind(this),\n    DropTableNode: this.transformDropTable.bind(this),\n    DataTypeNode: this.transformDataType.bind(this),\n    OrderByNode: this.transformOrderBy.bind(this),\n    OrderByItemNode: this.transformOrderByItem.bind(this),\n    GroupByNode: this.transformGroupBy.bind(this),\n    GroupByItemNode: this.transformGroupByItem.bind(this),\n    UpdateQueryNode: this.transformUpdateQuery.bind(this),\n    ColumnUpdateNode: this.transformColumnUpdate.bind(this),\n    LimitNode: this.transformLimit.bind(this),\n    OffsetNode: this.transformOffset.bind(this),\n    OnConflictNode: this.transformOnConflict.bind(this),\n    OnDuplicateKeyNode: this.transformOnDuplicateKey.bind(this),\n    CreateIndexNode: this.transformCreateIndex.bind(this),\n    DropIndexNode: this.transformDropIndex.bind(this),\n    ListNode: this.transformList.bind(this),\n    PrimaryKeyConstraintNode: this.transformPrimaryKeyConstraint.bind(this),\n    UniqueConstraintNode: this.transformUniqueConstraint.bind(this),\n    ReferencesNode: this.transformReferences.bind(this),\n    CheckConstraintNode: this.transformCheckConstraint.bind(this),\n    WithNode: this.transformWith.bind(this),\n    CommonTableExpressionNode: this.transformCommonTableExpression.bind(this),\n    CommonTableExpressionNameNode:\n      this.transformCommonTableExpressionName.bind(this),\n    HavingNode: this.transformHaving.bind(this),\n    CreateSchemaNode: this.transformCreateSchema.bind(this),\n    DropSchemaNode: this.transformDropSchema.bind(this),\n    AlterTableNode: this.transformAlterTable.bind(this),\n    DropColumnNode: this.transformDropColumn.bind(this),\n    RenameColumnNode: this.transformRenameColumn.bind(this),\n    AlterColumnNode: this.transformAlterColumn.bind(this),\n    ModifyColumnNode: this.transformModifyColumn.bind(this),\n    AddConstraintNode: this.transformAddConstraint.bind(this),\n    DropConstraintNode: this.transformDropConstraint.bind(this),\n    RenameConstraintNode: this.transformRenameConstraint.bind(this),\n    ForeignKeyConstraintNode: this.transformForeignKeyConstraint.bind(this),\n    CreateViewNode: this.transformCreateView.bind(this),\n    RefreshMaterializedViewNode:\n      this.transformRefreshMaterializedView.bind(this),\n    DropViewNode: this.transformDropView.bind(this),\n    GeneratedNode: this.transformGenerated.bind(this),\n    DefaultValueNode: this.transformDefaultValue.bind(this),\n    OnNode: this.transformOn.bind(this),\n    ValuesNode: this.transformValues.bind(this),\n    SelectModifierNode: this.transformSelectModifier.bind(this),\n    CreateTypeNode: this.transformCreateType.bind(this),\n    DropTypeNode: this.transformDropType.bind(this),\n    ExplainNode: this.transformExplain.bind(this),\n    DefaultInsertValueNode: this.transformDefaultInsertValue.bind(this),\n    AggregateFunctionNode: this.transformAggregateFunction.bind(this),\n    OverNode: this.transformOver.bind(this),\n    PartitionByNode: this.transformPartitionBy.bind(this),\n    PartitionByItemNode: this.transformPartitionByItem.bind(this),\n    SetOperationNode: this.transformSetOperation.bind(this),\n    BinaryOperationNode: this.transformBinaryOperation.bind(this),\n    UnaryOperationNode: this.transformUnaryOperation.bind(this),\n    UsingNode: this.transformUsing.bind(this),\n    FunctionNode: this.transformFunction.bind(this),\n    CaseNode: this.transformCase.bind(this),\n    WhenNode: this.transformWhen.bind(this),\n    JSONReferenceNode: this.transformJSONReference.bind(this),\n    JSONPathNode: this.transformJSONPath.bind(this),\n    JSONPathLegNode: this.transformJSONPathLeg.bind(this),\n    JSONOperatorChainNode: this.transformJSONOperatorChain.bind(this),\n    TupleNode: this.transformTuple.bind(this),\n    MergeQueryNode: this.transformMergeQuery.bind(this),\n    MatchedNode: this.transformMatched.bind(this),\n    AddIndexNode: this.transformAddIndex.bind(this),\n    CastNode: this.transformCast.bind(this),\n    FetchNode: this.transformFetch.bind(this),\n    TopNode: this.transformTop.bind(this),\n    OutputNode: this.transformOutput.bind(this),\n    OrActionNode: this.transformOrAction.bind(this),\n    CollateNode: this.transformCollate.bind(this),\n  })\n\n  transformNode<T extends OperationNode | undefined>(\n    node: T,\n    queryId?: QueryId,\n  ): T {\n    if (!node) {\n      return node\n    }\n\n    this.nodeStack.push(node)\n    const out = this.transformNodeImpl(node, queryId)\n    this.nodeStack.pop()\n\n    return freeze(out) as T\n  }\n\n  protected transformNodeImpl<T extends OperationNode>(\n    node: T,\n    queryId?: QueryId,\n  ): T {\n    return this.#transformers[node.kind](node, queryId)\n  }\n\n  protected transformNodeList<\n    T extends ReadonlyArray<OperationNode> | undefined,\n  >(list: T, queryId?: QueryId): T {\n    if (!list) {\n      return list\n    }\n\n    return freeze(list.map((node) => this.transformNode(node, queryId))) as T\n  }\n\n  protected transformSelectQuery(\n    node: SelectQueryNode,\n    queryId?: QueryId,\n  ): SelectQueryNode {\n    return requireAllProps<SelectQueryNode>({\n      kind: 'SelectQueryNode',\n      from: this.transformNode(node.from, queryId),\n      selections: this.transformNodeList(node.selections, queryId),\n      distinctOn: this.transformNodeList(node.distinctOn, queryId),\n      joins: this.transformNodeList(node.joins, queryId),\n      groupBy: this.transformNode(node.groupBy, queryId),\n      orderBy: this.transformNode(node.orderBy, queryId),\n      where: this.transformNode(node.where, queryId),\n      frontModifiers: this.transformNodeList(node.frontModifiers, queryId),\n      endModifiers: this.transformNodeList(node.endModifiers, queryId),\n      limit: this.transformNode(node.limit, queryId),\n      offset: this.transformNode(node.offset, queryId),\n      with: this.transformNode(node.with, queryId),\n      having: this.transformNode(node.having, queryId),\n      explain: this.transformNode(node.explain, queryId),\n      setOperations: this.transformNodeList(node.setOperations, queryId),\n      fetch: this.transformNode(node.fetch, queryId),\n      top: this.transformNode(node.top, queryId),\n    })\n  }\n\n  protected transformSelection(\n    node: SelectionNode,\n    queryId?: QueryId,\n  ): SelectionNode {\n    return requireAllProps<SelectionNode>({\n      kind: 'SelectionNode',\n      selection: this.transformNode(node.selection, queryId),\n    })\n  }\n\n  protected transformColumn(node: ColumnNode, queryId?: QueryId): ColumnNode {\n    return requireAllProps<ColumnNode>({\n      kind: 'ColumnNode',\n      column: this.transformNode(node.column, queryId),\n    })\n  }\n\n  protected transformAlias(node: AliasNode, queryId?: QueryId): AliasNode {\n    return requireAllProps<AliasNode>({\n      kind: 'AliasNode',\n      node: this.transformNode(node.node, queryId),\n      alias: this.transformNode(node.alias, queryId),\n    })\n  }\n\n  protected transformTable(node: TableNode, queryId?: QueryId): TableNode {\n    return requireAllProps<TableNode>({\n      kind: 'TableNode',\n      table: this.transformNode(node.table, queryId),\n    })\n  }\n\n  protected transformFrom(node: FromNode, queryId?: QueryId): FromNode {\n    return requireAllProps<FromNode>({\n      kind: 'FromNode',\n      froms: this.transformNodeList(node.froms, queryId),\n    })\n  }\n\n  protected transformReference(\n    node: ReferenceNode,\n    queryId?: QueryId,\n  ): ReferenceNode {\n    return requireAllProps<ReferenceNode>({\n      kind: 'ReferenceNode',\n      column: this.transformNode(node.column, queryId),\n      table: this.transformNode(node.table, queryId),\n    })\n  }\n\n  protected transformAnd(node: AndNode, queryId?: QueryId): AndNode {\n    return requireAllProps<AndNode>({\n      kind: 'AndNode',\n      left: this.transformNode(node.left, queryId),\n      right: this.transformNode(node.right, queryId),\n    })\n  }\n\n  protected transformOr(node: OrNode, queryId?: QueryId): OrNode {\n    return requireAllProps<OrNode>({\n      kind: 'OrNode',\n      left: this.transformNode(node.left, queryId),\n      right: this.transformNode(node.right, queryId),\n    })\n  }\n\n  protected transformValueList(\n    node: ValueListNode,\n    queryId?: QueryId,\n  ): ValueListNode {\n    return requireAllProps<ValueListNode>({\n      kind: 'ValueListNode',\n      values: this.transformNodeList(node.values, queryId),\n    })\n  }\n\n  protected transformParens(node: ParensNode, queryId?: QueryId): ParensNode {\n    return requireAllProps<ParensNode>({\n      kind: 'ParensNode',\n      node: this.transformNode(node.node, queryId),\n    })\n  }\n\n  protected transformJoin(node: JoinNode, queryId?: QueryId): JoinNode {\n    return requireAllProps<JoinNode>({\n      kind: 'JoinNode',\n      joinType: node.joinType,\n      table: this.transformNode(node.table, queryId),\n      on: this.transformNode(node.on, queryId),\n    })\n  }\n\n  protected transformRaw(node: RawNode, queryId?: QueryId): RawNode {\n    return requireAllProps<RawNode>({\n      kind: 'RawNode',\n      sqlFragments: freeze([...node.sqlFragments]),\n      parameters: this.transformNodeList(node.parameters, queryId),\n    })\n  }\n\n  protected transformWhere(node: WhereNode, queryId?: QueryId): WhereNode {\n    return requireAllProps<WhereNode>({\n      kind: 'WhereNode',\n      where: this.transformNode(node.where, queryId),\n    })\n  }\n\n  protected transformInsertQuery(\n    node: InsertQueryNode,\n    queryId?: QueryId,\n  ): InsertQueryNode {\n    return requireAllProps<InsertQueryNode>({\n      kind: 'InsertQueryNode',\n      into: this.transformNode(node.into, queryId),\n      columns: this.transformNodeList(node.columns, queryId),\n      values: this.transformNode(node.values, queryId),\n      returning: this.transformNode(node.returning, queryId),\n      onConflict: this.transformNode(node.onConflict, queryId),\n      onDuplicateKey: this.transformNode(node.onDuplicateKey, queryId),\n      endModifiers: this.transformNodeList(node.endModifiers, queryId),\n      with: this.transformNode(node.with, queryId),\n      ignore: node.ignore,\n      orAction: this.transformNode(node.orAction, queryId),\n      replace: node.replace,\n      explain: this.transformNode(node.explain, queryId),\n      defaultValues: node.defaultValues,\n      top: this.transformNode(node.top, queryId),\n      output: this.transformNode(node.output, queryId),\n    })\n  }\n\n  protected transformValues(node: ValuesNode, queryId?: QueryId): ValuesNode {\n    return requireAllProps<ValuesNode>({\n      kind: 'ValuesNode',\n      values: this.transformNodeList(node.values, queryId),\n    })\n  }\n\n  protected transformDeleteQuery(\n    node: DeleteQueryNode,\n    queryId?: QueryId,\n  ): DeleteQueryNode {\n    return requireAllProps<DeleteQueryNode>({\n      kind: 'DeleteQueryNode',\n      from: this.transformNode(node.from, queryId),\n      using: this.transformNode(node.using, queryId),\n      joins: this.transformNodeList(node.joins, queryId),\n      where: this.transformNode(node.where, queryId),\n      returning: this.transformNode(node.returning, queryId),\n      endModifiers: this.transformNodeList(node.endModifiers, queryId),\n      with: this.transformNode(node.with, queryId),\n      orderBy: this.transformNode(node.orderBy, queryId),\n      limit: this.transformNode(node.limit, queryId),\n      explain: this.transformNode(node.explain, queryId),\n      top: this.transformNode(node.top, queryId),\n      output: this.transformNode(node.output, queryId),\n    })\n  }\n\n  protected transformReturning(\n    node: ReturningNode,\n    queryId?: QueryId,\n  ): ReturningNode {\n    return requireAllProps<ReturningNode>({\n      kind: 'ReturningNode',\n      selections: this.transformNodeList(node.selections, queryId),\n    })\n  }\n\n  protected transformCreateTable(\n    node: CreateTableNode,\n    queryId?: QueryId,\n  ): CreateTableNode {\n    return requireAllProps<CreateTableNode>({\n      kind: 'CreateTableNode',\n      table: this.transformNode(node.table, queryId),\n      columns: this.transformNodeList(node.columns, queryId),\n      constraints: this.transformNodeList(node.constraints, queryId),\n      temporary: node.temporary,\n      ifNotExists: node.ifNotExists,\n      onCommit: node.onCommit,\n      frontModifiers: this.transformNodeList(node.frontModifiers, queryId),\n      endModifiers: this.transformNodeList(node.endModifiers, queryId),\n      selectQuery: this.transformNode(node.selectQuery, queryId),\n    })\n  }\n\n  protected transformColumnDefinition(\n    node: ColumnDefinitionNode,\n    queryId?: QueryId,\n  ): ColumnDefinitionNode {\n    return requireAllProps<ColumnDefinitionNode>({\n      kind: 'ColumnDefinitionNode',\n      column: this.transformNode(node.column, queryId),\n      dataType: this.transformNode(node.dataType, queryId),\n      references: this.transformNode(node.references, queryId),\n      primaryKey: node.primaryKey,\n      autoIncrement: node.autoIncrement,\n      unique: node.unique,\n      notNull: node.notNull,\n      unsigned: node.unsigned,\n      defaultTo: this.transformNode(node.defaultTo, queryId),\n      check: this.transformNode(node.check, queryId),\n      generated: this.transformNode(node.generated, queryId),\n      frontModifiers: this.transformNodeList(node.frontModifiers, queryId),\n      endModifiers: this.transformNodeList(node.endModifiers, queryId),\n      nullsNotDistinct: node.nullsNotDistinct,\n      identity: node.identity,\n      ifNotExists: node.ifNotExists,\n    })\n  }\n\n  protected transformAddColumn(\n    node: AddColumnNode,\n    queryId?: QueryId,\n  ): AddColumnNode {\n    return requireAllProps<AddColumnNode>({\n      kind: 'AddColumnNode',\n      column: this.transformNode(node.column, queryId),\n    })\n  }\n\n  protected transformDropTable(\n    node: DropTableNode,\n    queryId?: QueryId,\n  ): DropTableNode {\n    return requireAllProps<DropTableNode>({\n      kind: 'DropTableNode',\n      table: this.transformNode(node.table, queryId),\n      ifExists: node.ifExists,\n      cascade: node.cascade,\n    })\n  }\n\n  protected transformOrderBy(\n    node: OrderByNode,\n    queryId?: QueryId,\n  ): OrderByNode {\n    return requireAllProps<OrderByNode>({\n      kind: 'OrderByNode',\n      items: this.transformNodeList(node.items, queryId),\n    })\n  }\n\n  protected transformOrderByItem(\n    node: OrderByItemNode,\n    queryId?: QueryId,\n  ): OrderByItemNode {\n    return requireAllProps<OrderByItemNode>({\n      kind: 'OrderByItemNode',\n      orderBy: this.transformNode(node.orderBy, queryId),\n      direction: this.transformNode(node.direction, queryId),\n      collation: this.transformNode(node.collation, queryId),\n      nulls: node.nulls,\n    })\n  }\n\n  protected transformGroupBy(\n    node: GroupByNode,\n    queryId?: QueryId,\n  ): GroupByNode {\n    return requireAllProps<GroupByNode>({\n      kind: 'GroupByNode',\n      items: this.transformNodeList(node.items, queryId),\n    })\n  }\n\n  protected transformGroupByItem(\n    node: GroupByItemNode,\n    queryId?: QueryId,\n  ): GroupByItemNode {\n    return requireAllProps<GroupByItemNode>({\n      kind: 'GroupByItemNode',\n      groupBy: this.transformNode(node.groupBy, queryId),\n    })\n  }\n\n  protected transformUpdateQuery(\n    node: UpdateQueryNode,\n    queryId?: QueryId,\n  ): UpdateQueryNode {\n    return requireAllProps<UpdateQueryNode>({\n      kind: 'UpdateQueryNode',\n      table: this.transformNode(node.table, queryId),\n      from: this.transformNode(node.from, queryId),\n      joins: this.transformNodeList(node.joins, queryId),\n      where: this.transformNode(node.where, queryId),\n      updates: this.transformNodeList(node.updates, queryId),\n      returning: this.transformNode(node.returning, queryId),\n      endModifiers: this.transformNodeList(node.endModifiers, queryId),\n      with: this.transformNode(node.with, queryId),\n      explain: this.transformNode(node.explain, queryId),\n      limit: this.transformNode(node.limit, queryId),\n      top: this.transformNode(node.top, queryId),\n      output: this.transformNode(node.output, queryId),\n      orderBy: this.transformNode(node.orderBy, queryId),\n    })\n  }\n\n  protected transformColumnUpdate(\n    node: ColumnUpdateNode,\n    queryId?: QueryId,\n  ): ColumnUpdateNode {\n    return requireAllProps<ColumnUpdateNode>({\n      kind: 'ColumnUpdateNode',\n      column: this.transformNode(node.column, queryId),\n      value: this.transformNode(node.value, queryId),\n    })\n  }\n\n  protected transformLimit(node: LimitNode, queryId?: QueryId): LimitNode {\n    return requireAllProps<LimitNode>({\n      kind: 'LimitNode',\n      limit: this.transformNode(node.limit, queryId),\n    })\n  }\n\n  protected transformOffset(node: OffsetNode, queryId?: QueryId): OffsetNode {\n    return requireAllProps<OffsetNode>({\n      kind: 'OffsetNode',\n      offset: this.transformNode(node.offset, queryId),\n    })\n  }\n\n  protected transformOnConflict(\n    node: OnConflictNode,\n    queryId?: QueryId,\n  ): OnConflictNode {\n    return requireAllProps<OnConflictNode>({\n      kind: 'OnConflictNode',\n      columns: this.transformNodeList(node.columns, queryId),\n      constraint: this.transformNode(node.constraint, queryId),\n      indexExpression: this.transformNode(node.indexExpression, queryId),\n      indexWhere: this.transformNode(node.indexWhere, queryId),\n      updates: this.transformNodeList(node.updates, queryId),\n      updateWhere: this.transformNode(node.updateWhere, queryId),\n      doNothing: node.doNothing,\n    })\n  }\n\n  protected transformOnDuplicateKey(\n    node: OnDuplicateKeyNode,\n    queryId?: QueryId,\n  ): OnDuplicateKeyNode {\n    return requireAllProps<OnDuplicateKeyNode>({\n      kind: 'OnDuplicateKeyNode',\n      updates: this.transformNodeList(node.updates, queryId),\n    })\n  }\n\n  protected transformCreateIndex(\n    node: CreateIndexNode,\n    queryId?: QueryId,\n  ): CreateIndexNode {\n    return requireAllProps<CreateIndexNode>({\n      kind: 'CreateIndexNode',\n      name: this.transformNode(node.name, queryId),\n      table: this.transformNode(node.table, queryId),\n      columns: this.transformNodeList(node.columns, queryId),\n      unique: node.unique,\n      using: this.transformNode(node.using, queryId),\n      ifNotExists: node.ifNotExists,\n      where: this.transformNode(node.where, queryId),\n      nullsNotDistinct: node.nullsNotDistinct,\n    })\n  }\n\n  protected transformList(node: ListNode, queryId?: QueryId): ListNode {\n    return requireAllProps<ListNode>({\n      kind: 'ListNode',\n      items: this.transformNodeList(node.items, queryId),\n    })\n  }\n\n  protected transformDropIndex(\n    node: DropIndexNode,\n    queryId?: QueryId,\n  ): DropIndexNode {\n    return requireAllProps<DropIndexNode>({\n      kind: 'DropIndexNode',\n      name: this.transformNode(node.name, queryId),\n      table: this.transformNode(node.table, queryId),\n      ifExists: node.ifExists,\n      cascade: node.cascade,\n    })\n  }\n\n  protected transformPrimaryKeyConstraint(\n    node: PrimaryKeyConstraintNode,\n    queryId?: QueryId,\n  ): PrimaryKeyConstraintNode {\n    return requireAllProps<PrimaryKeyConstraintNode>({\n      kind: 'PrimaryKeyConstraintNode',\n      columns: this.transformNodeList(node.columns, queryId),\n      name: this.transformNode(node.name, queryId),\n      deferrable: node.deferrable,\n      initiallyDeferred: node.initiallyDeferred,\n    })\n  }\n\n  protected transformUniqueConstraint(\n    node: UniqueConstraintNode,\n    queryId?: QueryId,\n  ): UniqueConstraintNode {\n    return requireAllProps<UniqueConstraintNode>({\n      kind: 'UniqueConstraintNode',\n      columns: this.transformNodeList(node.columns, queryId),\n      name: this.transformNode(node.name, queryId),\n      nullsNotDistinct: node.nullsNotDistinct,\n      deferrable: node.deferrable,\n      initiallyDeferred: node.initiallyDeferred,\n    })\n  }\n\n  protected transformForeignKeyConstraint(\n    node: ForeignKeyConstraintNode,\n    queryId?: QueryId,\n  ): ForeignKeyConstraintNode {\n    return requireAllProps<ForeignKeyConstraintNode>({\n      kind: 'ForeignKeyConstraintNode',\n      columns: this.transformNodeList(node.columns, queryId),\n      references: this.transformNode(node.references, queryId),\n      name: this.transformNode(node.name, queryId),\n      onDelete: node.onDelete,\n      onUpdate: node.onUpdate,\n      deferrable: node.deferrable,\n      initiallyDeferred: node.initiallyDeferred,\n    })\n  }\n\n  protected transformSetOperation(\n    node: SetOperationNode,\n    queryId?: QueryId,\n  ): SetOperationNode {\n    return requireAllProps<SetOperationNode>({\n      kind: 'SetOperationNode',\n      operator: node.operator,\n      expression: this.transformNode(node.expression, queryId),\n      all: node.all,\n    })\n  }\n\n  protected transformReferences(\n    node: ReferencesNode,\n    queryId?: QueryId,\n  ): ReferencesNode {\n    return requireAllProps<ReferencesNode>({\n      kind: 'ReferencesNode',\n      table: this.transformNode(node.table, queryId),\n      columns: this.transformNodeList(node.columns, queryId),\n      onDelete: node.onDelete,\n      onUpdate: node.onUpdate,\n    })\n  }\n\n  protected transformCheckConstraint(\n    node: CheckConstraintNode,\n    queryId?: QueryId,\n  ): CheckConstraintNode {\n    return requireAllProps<CheckConstraintNode>({\n      kind: 'CheckConstraintNode',\n      expression: this.transformNode(node.expression, queryId),\n      name: this.transformNode(node.name, queryId),\n    })\n  }\n\n  protected transformWith(node: WithNode, queryId?: QueryId): WithNode {\n    return requireAllProps<WithNode>({\n      kind: 'WithNode',\n      expressions: this.transformNodeList(node.expressions, queryId),\n      recursive: node.recursive,\n    })\n  }\n\n  protected transformCommonTableExpression(\n    node: CommonTableExpressionNode,\n    queryId?: QueryId,\n  ): CommonTableExpressionNode {\n    return requireAllProps<CommonTableExpressionNode>({\n      kind: 'CommonTableExpressionNode',\n      name: this.transformNode(node.name, queryId),\n      materialized: node.materialized,\n      expression: this.transformNode(node.expression, queryId),\n    })\n  }\n\n  protected transformCommonTableExpressionName(\n    node: CommonTableExpressionNameNode,\n    queryId?: QueryId,\n  ): CommonTableExpressionNameNode {\n    return requireAllProps<CommonTableExpressionNameNode>({\n      kind: 'CommonTableExpressionNameNode',\n      table: this.transformNode(node.table, queryId),\n      columns: this.transformNodeList(node.columns, queryId),\n    })\n  }\n\n  protected transformHaving(node: HavingNode, queryId?: QueryId): HavingNode {\n    return requireAllProps<HavingNode>({\n      kind: 'HavingNode',\n      having: this.transformNode(node.having, queryId),\n    })\n  }\n\n  protected transformCreateSchema(\n    node: CreateSchemaNode,\n    queryId?: QueryId,\n  ): CreateSchemaNode {\n    return requireAllProps<CreateSchemaNode>({\n      kind: 'CreateSchemaNode',\n      schema: this.transformNode(node.schema, queryId),\n      ifNotExists: node.ifNotExists,\n    })\n  }\n\n  protected transformDropSchema(\n    node: DropSchemaNode,\n    queryId?: QueryId,\n  ): DropSchemaNode {\n    return requireAllProps<DropSchemaNode>({\n      kind: 'DropSchemaNode',\n      schema: this.transformNode(node.schema, queryId),\n      ifExists: node.ifExists,\n      cascade: node.cascade,\n    })\n  }\n\n  protected transformAlterTable(\n    node: AlterTableNode,\n    queryId?: QueryId,\n  ): AlterTableNode {\n    return requireAllProps<AlterTableNode>({\n      kind: 'AlterTableNode',\n      table: this.transformNode(node.table, queryId),\n      renameTo: this.transformNode(node.renameTo, queryId),\n      setSchema: this.transformNode(node.setSchema, queryId),\n      columnAlterations: this.transformNodeList(\n        node.columnAlterations,\n        queryId,\n      ),\n      addConstraint: this.transformNode(node.addConstraint, queryId),\n      dropConstraint: this.transformNode(node.dropConstraint, queryId),\n      renameConstraint: this.transformNode(node.renameConstraint, queryId),\n      addIndex: this.transformNode(node.addIndex, queryId),\n      dropIndex: this.transformNode(node.dropIndex, queryId),\n    })\n  }\n\n  protected transformDropColumn(\n    node: DropColumnNode,\n    queryId?: QueryId,\n  ): DropColumnNode {\n    return requireAllProps<DropColumnNode>({\n      kind: 'DropColumnNode',\n      column: this.transformNode(node.column, queryId),\n    })\n  }\n\n  protected transformRenameColumn(\n    node: RenameColumnNode,\n    queryId?: QueryId,\n  ): RenameColumnNode {\n    return requireAllProps<RenameColumnNode>({\n      kind: 'RenameColumnNode',\n      column: this.transformNode(node.column, queryId),\n      renameTo: this.transformNode(node.renameTo, queryId),\n    })\n  }\n\n  protected transformAlterColumn(\n    node: AlterColumnNode,\n    queryId?: QueryId,\n  ): AlterColumnNode {\n    return requireAllProps<AlterColumnNode>({\n      kind: 'AlterColumnNode',\n      column: this.transformNode(node.column, queryId),\n      dataType: this.transformNode(node.dataType, queryId),\n      dataTypeExpression: this.transformNode(node.dataTypeExpression, queryId),\n      setDefault: this.transformNode(node.setDefault, queryId),\n      dropDefault: node.dropDefault,\n      setNotNull: node.setNotNull,\n      dropNotNull: node.dropNotNull,\n    })\n  }\n\n  protected transformModifyColumn(\n    node: ModifyColumnNode,\n    queryId?: QueryId,\n  ): ModifyColumnNode {\n    return requireAllProps<ModifyColumnNode>({\n      kind: 'ModifyColumnNode',\n      column: this.transformNode(node.column, queryId),\n    })\n  }\n\n  protected transformAddConstraint(\n    node: AddConstraintNode,\n    queryId?: QueryId,\n  ): AddConstraintNode {\n    return requireAllProps<AddConstraintNode>({\n      kind: 'AddConstraintNode',\n      constraint: this.transformNode(node.constraint, queryId),\n    })\n  }\n\n  protected transformDropConstraint(\n    node: DropConstraintNode,\n    queryId?: QueryId,\n  ): DropConstraintNode {\n    return requireAllProps<DropConstraintNode>({\n      kind: 'DropConstraintNode',\n      constraintName: this.transformNode(node.constraintName, queryId),\n      ifExists: node.ifExists,\n      modifier: node.modifier,\n    })\n  }\n\n  protected transformRenameConstraint(\n    node: RenameConstraintNode,\n    queryId?: QueryId,\n  ): RenameConstraintNode {\n    return requireAllProps<RenameConstraintNode>({\n      kind: 'RenameConstraintNode',\n      oldName: this.transformNode(node.oldName, queryId),\n      newName: this.transformNode(node.newName, queryId),\n    })\n  }\n\n  protected transformCreateView(\n    node: CreateViewNode,\n    queryId?: QueryId,\n  ): CreateViewNode {\n    return requireAllProps<CreateViewNode>({\n      kind: 'CreateViewNode',\n      name: this.transformNode(node.name, queryId),\n      temporary: node.temporary,\n      orReplace: node.orReplace,\n      ifNotExists: node.ifNotExists,\n      materialized: node.materialized,\n      columns: this.transformNodeList(node.columns, queryId),\n      as: this.transformNode(node.as, queryId),\n    })\n  }\n\n  protected transformRefreshMaterializedView(\n    node: RefreshMaterializedViewNode,\n    queryId?: QueryId,\n  ): RefreshMaterializedViewNode {\n    return requireAllProps<RefreshMaterializedViewNode>({\n      kind: 'RefreshMaterializedViewNode',\n      name: this.transformNode(node.name, queryId),\n      concurrently: node.concurrently,\n      withNoData: node.withNoData,\n    })\n  }\n\n  protected transformDropView(\n    node: DropViewNode,\n    queryId?: QueryId,\n  ): DropViewNode {\n    return requireAllProps<DropViewNode>({\n      kind: 'DropViewNode',\n      name: this.transformNode(node.name, queryId),\n      ifExists: node.ifExists,\n      materialized: node.materialized,\n      cascade: node.cascade,\n    })\n  }\n\n  protected transformGenerated(\n    node: GeneratedNode,\n    queryId?: QueryId,\n  ): GeneratedNode {\n    return requireAllProps<GeneratedNode>({\n      kind: 'GeneratedNode',\n      byDefault: node.byDefault,\n      always: node.always,\n      identity: node.identity,\n      stored: node.stored,\n      expression: this.transformNode(node.expression, queryId),\n    })\n  }\n\n  protected transformDefaultValue(\n    node: DefaultValueNode,\n    queryId?: QueryId,\n  ): DefaultValueNode {\n    return requireAllProps<DefaultValueNode>({\n      kind: 'DefaultValueNode',\n      defaultValue: this.transformNode(node.defaultValue, queryId),\n    })\n  }\n\n  protected transformOn(node: OnNode, queryId?: QueryId): OnNode {\n    return requireAllProps<OnNode>({\n      kind: 'OnNode',\n      on: this.transformNode(node.on, queryId),\n    })\n  }\n\n  protected transformSelectModifier(\n    node: SelectModifierNode,\n    queryId?: QueryId,\n  ): SelectModifierNode {\n    return requireAllProps<SelectModifierNode>({\n      kind: 'SelectModifierNode',\n      modifier: node.modifier,\n      rawModifier: this.transformNode(node.rawModifier, queryId),\n      of: this.transformNodeList(node.of, queryId),\n    })\n  }\n\n  protected transformCreateType(\n    node: CreateTypeNode,\n    queryId?: QueryId,\n  ): CreateTypeNode {\n    return requireAllProps<CreateTypeNode>({\n      kind: 'CreateTypeNode',\n      name: this.transformNode(node.name, queryId),\n      enum: this.transformNode(node.enum, queryId),\n    })\n  }\n\n  protected transformDropType(\n    node: DropTypeNode,\n    queryId?: QueryId,\n  ): DropTypeNode {\n    return requireAllProps<DropTypeNode>({\n      kind: 'DropTypeNode',\n      name: this.transformNode(node.name, queryId),\n      ifExists: node.ifExists,\n    })\n  }\n\n  protected transformExplain(\n    node: ExplainNode,\n    queryId?: QueryId,\n  ): ExplainNode {\n    return requireAllProps({\n      kind: 'ExplainNode',\n      format: node.format,\n      options: this.transformNode(node.options, queryId),\n    })\n  }\n\n  protected transformSchemableIdentifier(\n    node: SchemableIdentifierNode,\n    queryId?: QueryId,\n  ): SchemableIdentifierNode {\n    return requireAllProps<SchemableIdentifierNode>({\n      kind: 'SchemableIdentifierNode',\n      schema: this.transformNode(node.schema, queryId),\n      identifier: this.transformNode(node.identifier, queryId),\n    })\n  }\n\n  protected transformAggregateFunction(\n    node: AggregateFunctionNode,\n    queryId?: QueryId,\n  ): AggregateFunctionNode {\n    return requireAllProps({\n      kind: 'AggregateFunctionNode',\n      func: node.func,\n      aggregated: this.transformNodeList(node.aggregated, queryId),\n      distinct: node.distinct,\n      orderBy: this.transformNode(node.orderBy, queryId),\n      withinGroup: this.transformNode(node.withinGroup, queryId),\n      filter: this.transformNode(node.filter, queryId),\n      over: this.transformNode(node.over, queryId),\n    })\n  }\n\n  protected transformOver(node: OverNode, queryId?: QueryId): OverNode {\n    return requireAllProps({\n      kind: 'OverNode',\n      orderBy: this.transformNode(node.orderBy, queryId),\n      partitionBy: this.transformNode(node.partitionBy, queryId),\n    })\n  }\n\n  protected transformPartitionBy(\n    node: PartitionByNode,\n    queryId?: QueryId,\n  ): PartitionByNode {\n    return requireAllProps({\n      kind: 'PartitionByNode',\n      items: this.transformNodeList(node.items, queryId),\n    })\n  }\n\n  protected transformPartitionByItem(\n    node: PartitionByItemNode,\n    queryId?: QueryId,\n  ): PartitionByItemNode {\n    return requireAllProps({\n      kind: 'PartitionByItemNode',\n      partitionBy: this.transformNode(node.partitionBy, queryId),\n    })\n  }\n\n  protected transformBinaryOperation(\n    node: BinaryOperationNode,\n    queryId?: QueryId,\n  ): BinaryOperationNode {\n    return requireAllProps<BinaryOperationNode>({\n      kind: 'BinaryOperationNode',\n      leftOperand: this.transformNode(node.leftOperand, queryId),\n      operator: this.transformNode(node.operator, queryId),\n      rightOperand: this.transformNode(node.rightOperand, queryId),\n    })\n  }\n\n  protected transformUnaryOperation(\n    node: UnaryOperationNode,\n    queryId?: QueryId,\n  ): UnaryOperationNode {\n    return requireAllProps<UnaryOperationNode>({\n      kind: 'UnaryOperationNode',\n      operator: this.transformNode(node.operator, queryId),\n      operand: this.transformNode(node.operand, queryId),\n    })\n  }\n\n  protected transformUsing(node: UsingNode, queryId?: QueryId): UsingNode {\n    return requireAllProps<UsingNode>({\n      kind: 'UsingNode',\n      tables: this.transformNodeList(node.tables, queryId),\n    })\n  }\n\n  protected transformFunction(\n    node: FunctionNode,\n    queryId?: QueryId,\n  ): FunctionNode {\n    return requireAllProps<FunctionNode>({\n      kind: 'FunctionNode',\n      func: node.func,\n      arguments: this.transformNodeList(node.arguments, queryId),\n    })\n  }\n\n  protected transformCase(node: CaseNode, queryId?: QueryId): CaseNode {\n    return requireAllProps<CaseNode>({\n      kind: 'CaseNode',\n      value: this.transformNode(node.value, queryId),\n      when: this.transformNodeList(node.when, queryId),\n      else: this.transformNode(node.else, queryId),\n      isStatement: node.isStatement,\n    })\n  }\n\n  protected transformWhen(node: WhenNode, queryId?: QueryId): WhenNode {\n    return requireAllProps<WhenNode>({\n      kind: 'WhenNode',\n      condition: this.transformNode(node.condition, queryId),\n      result: this.transformNode(node.result, queryId),\n    })\n  }\n\n  protected transformJSONReference(\n    node: JSONReferenceNode,\n    queryId?: QueryId,\n  ): JSONReferenceNode {\n    return requireAllProps<JSONReferenceNode>({\n      kind: 'JSONReferenceNode',\n      reference: this.transformNode(node.reference, queryId),\n      traversal: this.transformNode(node.traversal, queryId),\n    })\n  }\n\n  protected transformJSONPath(\n    node: JSONPathNode,\n    queryId?: QueryId,\n  ): JSONPathNode {\n    return requireAllProps<JSONPathNode>({\n      kind: 'JSONPathNode',\n      inOperator: this.transformNode(node.inOperator, queryId),\n      pathLegs: this.transformNodeList(node.pathLegs, queryId),\n    })\n  }\n\n  protected transformJSONPathLeg(\n    node: JSONPathLegNode,\n    _queryId?: QueryId,\n  ): JSONPathLegNode {\n    return requireAllProps<JSONPathLegNode>({\n      kind: 'JSONPathLegNode',\n      type: node.type,\n      value: node.value,\n    })\n  }\n\n  protected transformJSONOperatorChain(\n    node: JSONOperatorChainNode,\n    queryId?: QueryId,\n  ): JSONOperatorChainNode {\n    return requireAllProps<JSONOperatorChainNode>({\n      kind: 'JSONOperatorChainNode',\n      operator: this.transformNode(node.operator, queryId),\n      values: this.transformNodeList(node.values, queryId),\n    })\n  }\n\n  protected transformTuple(node: TupleNode, queryId?: QueryId): TupleNode {\n    return requireAllProps<TupleNode>({\n      kind: 'TupleNode',\n      values: this.transformNodeList(node.values, queryId),\n    })\n  }\n\n  protected transformMergeQuery(\n    node: MergeQueryNode,\n    queryId?: QueryId,\n  ): MergeQueryNode {\n    return requireAllProps<MergeQueryNode>({\n      kind: 'MergeQueryNode',\n      into: this.transformNode(node.into, queryId),\n      using: this.transformNode(node.using, queryId),\n      whens: this.transformNodeList(node.whens, queryId),\n      with: this.transformNode(node.with, queryId),\n      top: this.transformNode(node.top, queryId),\n      endModifiers: this.transformNodeList(node.endModifiers, queryId),\n      output: this.transformNode(node.output, queryId),\n      returning: this.transformNode(node.returning, queryId),\n    })\n  }\n\n  protected transformMatched(\n    node: MatchedNode,\n    _queryId?: QueryId,\n  ): MatchedNode {\n    return requireAllProps<MatchedNode>({\n      kind: 'MatchedNode',\n      not: node.not,\n      bySource: node.bySource,\n    })\n  }\n\n  protected transformAddIndex(\n    node: AddIndexNode,\n    queryId?: QueryId,\n  ): AddIndexNode {\n    return requireAllProps<AddIndexNode>({\n      kind: 'AddIndexNode',\n      name: this.transformNode(node.name, queryId),\n      columns: this.transformNodeList(node.columns, queryId),\n      unique: node.unique,\n      using: this.transformNode(node.using, queryId),\n      ifNotExists: node.ifNotExists,\n    })\n  }\n\n  protected transformCast(node: CastNode, queryId?: QueryId): CastNode {\n    return requireAllProps<CastNode>({\n      kind: 'CastNode',\n      expression: this.transformNode(node.expression, queryId),\n      dataType: this.transformNode(node.dataType, queryId),\n    })\n  }\n\n  protected transformFetch(node: FetchNode, queryId?: QueryId): FetchNode {\n    return requireAllProps<FetchNode>({\n      kind: 'FetchNode',\n      rowCount: this.transformNode(node.rowCount, queryId),\n      modifier: node.modifier,\n    })\n  }\n\n  protected transformTop(node: TopNode, _queryId?: QueryId): TopNode {\n    return requireAllProps<TopNode>({\n      kind: 'TopNode',\n      expression: node.expression,\n      modifiers: node.modifiers,\n    })\n  }\n\n  protected transformOutput(node: OutputNode, queryId?: QueryId): OutputNode {\n    return requireAllProps<OutputNode>({\n      kind: 'OutputNode',\n      selections: this.transformNodeList(node.selections, queryId),\n    })\n  }\n\n  protected transformDataType(\n    node: DataTypeNode,\n    _queryId?: QueryId,\n  ): DataTypeNode {\n    // An Object.freezed leaf node. No need to clone.\n    return node\n  }\n\n  protected transformSelectAll(\n    node: SelectAllNode,\n    _queryId?: QueryId,\n  ): SelectAllNode {\n    // An Object.freezed leaf node. No need to clone.\n    return node\n  }\n\n  protected transformIdentifier(\n    node: IdentifierNode,\n    _queryId?: QueryId,\n  ): IdentifierNode {\n    // An Object.freezed leaf node. No need to clone.\n    return node\n  }\n\n  protected transformValue(node: ValueNode, _queryId?: QueryId): ValueNode {\n    // An Object.freezed leaf node. No need to clone.\n    return node\n  }\n\n  protected transformPrimitiveValueList(\n    node: PrimitiveValueListNode,\n    _queryId?: QueryId,\n  ): PrimitiveValueListNode {\n    // An Object.freezed leaf node. No need to clone.\n    return node\n  }\n\n  protected transformOperator(\n    node: OperatorNode,\n    _queryId?: QueryId,\n  ): OperatorNode {\n    // An Object.freezed leaf node. No need to clone.\n    return node\n  }\n\n  protected transformDefaultInsertValue(\n    node: DefaultInsertValueNode,\n    _queryId?: QueryId,\n  ): DefaultInsertValueNode {\n    // An Object.freezed leaf node. No need to clone.\n    return node\n  }\n\n  protected transformOrAction(\n    node: OrActionNode,\n    _queryId?: QueryId,\n  ): OrActionNode {\n    // An Object.freezed leaf node. No need to clone.\n    return node\n  }\n\n  protected transformCollate(\n    node: CollateNode,\n    _queryId?: QueryId,\n  ): CollateNode {\n    // An Object.freezed leaf node. No need to clone.\n    return node\n  }\n}\n"
  },
  {
    "path": "src/operation-node/operation-node-visitor.ts",
    "content": "import type { AliasNode } from '../operation-node/alias-node.js'\nimport type { ColumnNode } from '../operation-node/column-node.js'\nimport type { IdentifierNode } from '../operation-node/identifier-node.js'\nimport type {\n  OperationNode,\n  OperationNodeKind,\n} from '../operation-node/operation-node.js'\nimport type { ReferenceNode } from '../operation-node/reference-node.js'\nimport type { SelectAllNode } from '../operation-node/select-all-node.js'\nimport type { SelectionNode } from '../operation-node/selection-node.js'\nimport type { TableNode } from '../operation-node/table-node.js'\nimport type { AndNode } from './and-node.js'\nimport type { JoinNode } from './join-node.js'\nimport type { OrNode } from './or-node.js'\nimport type { ParensNode } from './parens-node.js'\nimport type { PrimitiveValueListNode } from './primitive-value-list-node.js'\nimport type { RawNode } from './raw-node.js'\nimport type { SelectQueryNode } from './select-query-node.js'\nimport type { ValueListNode } from './value-list-node.js'\nimport type { ValueNode } from './value-node.js'\nimport type { OperatorNode } from './operator-node.js'\nimport type { FromNode } from './from-node.js'\nimport type { WhereNode } from './where-node.js'\nimport type { InsertQueryNode } from './insert-query-node.js'\nimport type { DeleteQueryNode } from './delete-query-node.js'\nimport type { ReturningNode } from './returning-node.js'\nimport type { CreateTableNode } from './create-table-node.js'\nimport type { AddColumnNode } from './add-column-node.js'\nimport type { DropTableNode } from './drop-table-node.js'\nimport type { DataTypeNode } from './data-type-node.js'\nimport type { OrderByNode } from './order-by-node.js'\nimport type { OrderByItemNode } from './order-by-item-node.js'\nimport type { GroupByNode } from './group-by-node.js'\nimport type { GroupByItemNode } from './group-by-item-node.js'\nimport type { UpdateQueryNode } from './update-query-node.js'\nimport type { ColumnUpdateNode } from './column-update-node.js'\nimport type { LimitNode } from './limit-node.js'\nimport type { OffsetNode } from './offset-node.js'\nimport type { OnConflictNode } from './on-conflict-node.js'\nimport type { CreateIndexNode } from './create-index-node.js'\nimport type { ListNode } from './list-node.js'\nimport type { DropIndexNode } from './drop-index-node.js'\nimport type { PrimaryKeyConstraintNode } from './primary-key-constraint-node.js'\nimport type { UniqueConstraintNode } from './unique-constraint-node.js'\nimport type { ReferencesNode } from './references-node.js'\nimport type { CheckConstraintNode } from './check-constraint-node.js'\nimport type { WithNode } from './with-node.js'\nimport type { CommonTableExpressionNode } from './common-table-expression-node.js'\nimport type { CommonTableExpressionNameNode } from './common-table-expression-name-node.js'\nimport type { HavingNode } from './having-node.js'\nimport type { CreateSchemaNode } from './create-schema-node.js'\nimport type { DropSchemaNode } from './drop-schema-node.js'\nimport type { AlterTableNode } from './alter-table-node.js'\nimport type { DropColumnNode } from './drop-column-node.js'\nimport type { RenameColumnNode } from './rename-column-node.js'\nimport type { AlterColumnNode } from './alter-column-node.js'\nimport type { AddConstraintNode } from './add-constraint-node.js'\nimport type { DropConstraintNode } from './drop-constraint-node.js'\nimport type { ForeignKeyConstraintNode } from './foreign-key-constraint-node.js'\nimport type { ColumnDefinitionNode } from './column-definition-node.js'\nimport type { ModifyColumnNode } from './modify-column-node.js'\nimport type { OnDuplicateKeyNode } from './on-duplicate-key-node.js'\nimport type { CreateViewNode } from './create-view-node.js'\nimport type { DropViewNode } from './drop-view-node.js'\nimport type { GeneratedNode } from './generated-node.js'\nimport type { DefaultValueNode } from './default-value-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { OnNode } from './on-node.js'\nimport type { ValuesNode } from './values-node.js'\nimport type { SelectModifierNode } from './select-modifier-node.js'\nimport type { CreateTypeNode } from './create-type-node.js'\nimport type { DropTypeNode } from './drop-type-node.js'\nimport type { ExplainNode } from './explain-node.js'\nimport type { SchemableIdentifierNode } from './schemable-identifier-node.js'\nimport type { DefaultInsertValueNode } from './default-insert-value-node.js'\nimport type { AggregateFunctionNode } from './aggregate-function-node.js'\nimport type { OverNode } from './over-node.js'\nimport type { PartitionByNode } from './partition-by-node.js'\nimport type { PartitionByItemNode } from './partition-by-item-node.js'\nimport type { SetOperationNode } from './set-operation-node.js'\nimport type { BinaryOperationNode } from './binary-operation-node.js'\nimport type { UnaryOperationNode } from './unary-operation-node.js'\nimport type { UsingNode } from './using-node.js'\nimport type { FunctionNode } from './function-node.js'\nimport type { WhenNode } from './when-node.js'\nimport type { CaseNode } from './case-node.js'\nimport type { JSONReferenceNode } from './json-reference-node.js'\nimport type { JSONPathNode } from './json-path-node.js'\nimport type { JSONPathLegNode } from './json-path-leg-node.js'\nimport type { JSONOperatorChainNode } from './json-operator-chain-node.js'\nimport type { TupleNode } from './tuple-node.js'\nimport type { MergeQueryNode } from './merge-query-node.js'\nimport type { MatchedNode } from './matched-node.js'\nimport type { AddIndexNode } from './add-index-node.js'\nimport type { CastNode } from './cast-node.js'\nimport type { FetchNode } from './fetch-node.js'\nimport type { TopNode } from './top-node.js'\nimport type { OutputNode } from './output-node.js'\nimport type { RefreshMaterializedViewNode } from './refresh-materialized-view-node.js'\nimport type { OrActionNode } from './or-action-node.js'\nimport type { CollateNode } from './collate-node.js'\nimport type { RenameConstraintNode } from './rename-constraint-node.js'\n\nexport abstract class OperationNodeVisitor {\n  protected readonly nodeStack: OperationNode[] = []\n\n  protected get parentNode(): OperationNode | undefined {\n    return this.nodeStack[this.nodeStack.length - 2]\n  }\n\n  readonly #visitors: Record<OperationNodeKind, Function> = freeze({\n    AliasNode: this.visitAlias.bind(this),\n    ColumnNode: this.visitColumn.bind(this),\n    IdentifierNode: this.visitIdentifier.bind(this),\n    SchemableIdentifierNode: this.visitSchemableIdentifier.bind(this),\n    RawNode: this.visitRaw.bind(this),\n    ReferenceNode: this.visitReference.bind(this),\n    SelectQueryNode: this.visitSelectQuery.bind(this),\n    SelectionNode: this.visitSelection.bind(this),\n    TableNode: this.visitTable.bind(this),\n    FromNode: this.visitFrom.bind(this),\n    SelectAllNode: this.visitSelectAll.bind(this),\n    AndNode: this.visitAnd.bind(this),\n    OrNode: this.visitOr.bind(this),\n    ValueNode: this.visitValue.bind(this),\n    ValueListNode: this.visitValueList.bind(this),\n    PrimitiveValueListNode: this.visitPrimitiveValueList.bind(this),\n    ParensNode: this.visitParens.bind(this),\n    JoinNode: this.visitJoin.bind(this),\n    OperatorNode: this.visitOperator.bind(this),\n    WhereNode: this.visitWhere.bind(this),\n    InsertQueryNode: this.visitInsertQuery.bind(this),\n    DeleteQueryNode: this.visitDeleteQuery.bind(this),\n    ReturningNode: this.visitReturning.bind(this),\n    CreateTableNode: this.visitCreateTable.bind(this),\n    AddColumnNode: this.visitAddColumn.bind(this),\n    ColumnDefinitionNode: this.visitColumnDefinition.bind(this),\n    DropTableNode: this.visitDropTable.bind(this),\n    DataTypeNode: this.visitDataType.bind(this),\n    OrderByNode: this.visitOrderBy.bind(this),\n    OrderByItemNode: this.visitOrderByItem.bind(this),\n    GroupByNode: this.visitGroupBy.bind(this),\n    GroupByItemNode: this.visitGroupByItem.bind(this),\n    UpdateQueryNode: this.visitUpdateQuery.bind(this),\n    ColumnUpdateNode: this.visitColumnUpdate.bind(this),\n    LimitNode: this.visitLimit.bind(this),\n    OffsetNode: this.visitOffset.bind(this),\n    OnConflictNode: this.visitOnConflict.bind(this),\n    OnDuplicateKeyNode: this.visitOnDuplicateKey.bind(this),\n    CreateIndexNode: this.visitCreateIndex.bind(this),\n    DropIndexNode: this.visitDropIndex.bind(this),\n    ListNode: this.visitList.bind(this),\n    PrimaryKeyConstraintNode: this.visitPrimaryKeyConstraint.bind(this),\n    UniqueConstraintNode: this.visitUniqueConstraint.bind(this),\n    ReferencesNode: this.visitReferences.bind(this),\n    CheckConstraintNode: this.visitCheckConstraint.bind(this),\n    WithNode: this.visitWith.bind(this),\n    CommonTableExpressionNode: this.visitCommonTableExpression.bind(this),\n    CommonTableExpressionNameNode:\n      this.visitCommonTableExpressionName.bind(this),\n    HavingNode: this.visitHaving.bind(this),\n    CreateSchemaNode: this.visitCreateSchema.bind(this),\n    DropSchemaNode: this.visitDropSchema.bind(this),\n    AlterTableNode: this.visitAlterTable.bind(this),\n    DropColumnNode: this.visitDropColumn.bind(this),\n    RenameColumnNode: this.visitRenameColumn.bind(this),\n    AlterColumnNode: this.visitAlterColumn.bind(this),\n    ModifyColumnNode: this.visitModifyColumn.bind(this),\n    AddConstraintNode: this.visitAddConstraint.bind(this),\n    DropConstraintNode: this.visitDropConstraint.bind(this),\n    RenameConstraintNode: this.visitRenameConstraint.bind(this),\n    ForeignKeyConstraintNode: this.visitForeignKeyConstraint.bind(this),\n    CreateViewNode: this.visitCreateView.bind(this),\n    RefreshMaterializedViewNode: this.visitRefreshMaterializedView.bind(this),\n    DropViewNode: this.visitDropView.bind(this),\n    GeneratedNode: this.visitGenerated.bind(this),\n    DefaultValueNode: this.visitDefaultValue.bind(this),\n    OnNode: this.visitOn.bind(this),\n    ValuesNode: this.visitValues.bind(this),\n    SelectModifierNode: this.visitSelectModifier.bind(this),\n    CreateTypeNode: this.visitCreateType.bind(this),\n    DropTypeNode: this.visitDropType.bind(this),\n    ExplainNode: this.visitExplain.bind(this),\n    DefaultInsertValueNode: this.visitDefaultInsertValue.bind(this),\n    AggregateFunctionNode: this.visitAggregateFunction.bind(this),\n    OverNode: this.visitOver.bind(this),\n    PartitionByNode: this.visitPartitionBy.bind(this),\n    PartitionByItemNode: this.visitPartitionByItem.bind(this),\n    SetOperationNode: this.visitSetOperation.bind(this),\n    BinaryOperationNode: this.visitBinaryOperation.bind(this),\n    UnaryOperationNode: this.visitUnaryOperation.bind(this),\n    UsingNode: this.visitUsing.bind(this),\n    FunctionNode: this.visitFunction.bind(this),\n    CaseNode: this.visitCase.bind(this),\n    WhenNode: this.visitWhen.bind(this),\n    JSONReferenceNode: this.visitJSONReference.bind(this),\n    JSONPathNode: this.visitJSONPath.bind(this),\n    JSONPathLegNode: this.visitJSONPathLeg.bind(this),\n    JSONOperatorChainNode: this.visitJSONOperatorChain.bind(this),\n    TupleNode: this.visitTuple.bind(this),\n    MergeQueryNode: this.visitMergeQuery.bind(this),\n    MatchedNode: this.visitMatched.bind(this),\n    AddIndexNode: this.visitAddIndex.bind(this),\n    CastNode: this.visitCast.bind(this),\n    FetchNode: this.visitFetch.bind(this),\n    TopNode: this.visitTop.bind(this),\n    OutputNode: this.visitOutput.bind(this),\n    OrActionNode: this.visitOrAction.bind(this),\n    CollateNode: this.visitCollate.bind(this),\n  })\n\n  protected readonly visitNode = (node: OperationNode): void => {\n    this.nodeStack.push(node)\n    this.#visitors[node.kind](node)\n    this.nodeStack.pop()\n  }\n\n  protected abstract visitSelectQuery(node: SelectQueryNode): void\n  protected abstract visitSelection(node: SelectionNode): void\n  protected abstract visitColumn(node: ColumnNode): void\n  protected abstract visitAlias(node: AliasNode): void\n  protected abstract visitTable(node: TableNode): void\n  protected abstract visitFrom(node: FromNode): void\n  protected abstract visitReference(node: ReferenceNode): void\n  protected abstract visitAnd(node: AndNode): void\n  protected abstract visitOr(node: OrNode): void\n  protected abstract visitValueList(node: ValueListNode): void\n  protected abstract visitParens(node: ParensNode): void\n  protected abstract visitJoin(node: JoinNode): void\n  protected abstract visitRaw(node: RawNode): void\n  protected abstract visitWhere(node: WhereNode): void\n  protected abstract visitInsertQuery(node: InsertQueryNode): void\n  protected abstract visitDeleteQuery(node: DeleteQueryNode): void\n  protected abstract visitReturning(node: ReturningNode): void\n  protected abstract visitCreateTable(node: CreateTableNode): void\n  protected abstract visitAddColumn(node: AddColumnNode): void\n  protected abstract visitColumnDefinition(node: ColumnDefinitionNode): void\n  protected abstract visitDropTable(node: DropTableNode): void\n  protected abstract visitOrderBy(node: OrderByNode): void\n  protected abstract visitOrderByItem(node: OrderByItemNode): void\n  protected abstract visitGroupBy(node: GroupByNode): void\n  protected abstract visitGroupByItem(node: GroupByItemNode): void\n  protected abstract visitUpdateQuery(node: UpdateQueryNode): void\n  protected abstract visitColumnUpdate(node: ColumnUpdateNode): void\n  protected abstract visitLimit(node: LimitNode): void\n  protected abstract visitOffset(node: OffsetNode): void\n  protected abstract visitOnConflict(node: OnConflictNode): void\n  protected abstract visitOnDuplicateKey(node: OnDuplicateKeyNode): void\n  protected abstract visitCreateIndex(node: CreateIndexNode): void\n  protected abstract visitDropIndex(node: DropIndexNode): void\n  protected abstract visitList(node: ListNode): void\n  protected abstract visitPrimaryKeyConstraint(\n    node: PrimaryKeyConstraintNode,\n  ): void\n  protected abstract visitUniqueConstraint(node: UniqueConstraintNode): void\n  protected abstract visitReferences(node: ReferencesNode): void\n  protected abstract visitCheckConstraint(node: CheckConstraintNode): void\n  protected abstract visitWith(node: WithNode): void\n  protected abstract visitCommonTableExpression(\n    node: CommonTableExpressionNode,\n  ): void\n  protected abstract visitCommonTableExpressionName(\n    node: CommonTableExpressionNameNode,\n  ): void\n  protected abstract visitHaving(node: HavingNode): void\n  protected abstract visitCreateSchema(node: CreateSchemaNode): void\n  protected abstract visitDropSchema(node: DropSchemaNode): void\n  protected abstract visitAlterTable(node: AlterTableNode): void\n  protected abstract visitDropColumn(node: DropColumnNode): void\n  protected abstract visitRenameColumn(node: RenameColumnNode): void\n  protected abstract visitAlterColumn(node: AlterColumnNode): void\n  protected abstract visitModifyColumn(node: ModifyColumnNode): void\n  protected abstract visitAddConstraint(node: AddConstraintNode): void\n  protected abstract visitDropConstraint(node: DropConstraintNode): void\n  protected abstract visitRenameConstraint(node: RenameConstraintNode): void\n  protected abstract visitForeignKeyConstraint(\n    node: ForeignKeyConstraintNode,\n  ): void\n  protected abstract visitDataType(node: DataTypeNode): void\n  protected abstract visitSelectAll(node: SelectAllNode): void\n  protected abstract visitIdentifier(node: IdentifierNode): void\n  protected abstract visitSchemableIdentifier(\n    node: SchemableIdentifierNode,\n  ): void\n  protected abstract visitValue(node: ValueNode): void\n  protected abstract visitPrimitiveValueList(node: PrimitiveValueListNode): void\n  protected abstract visitOperator(node: OperatorNode): void\n  protected abstract visitCreateView(node: CreateViewNode): void\n  protected abstract visitRefreshMaterializedView(\n    node: RefreshMaterializedViewNode,\n  ): void\n  protected abstract visitDropView(node: DropViewNode): void\n  protected abstract visitGenerated(node: GeneratedNode): void\n  protected abstract visitDefaultValue(node: DefaultValueNode): void\n  protected abstract visitOn(node: OnNode): void\n  protected abstract visitValues(node: ValuesNode): void\n  protected abstract visitSelectModifier(node: SelectModifierNode): void\n  protected abstract visitCreateType(node: CreateTypeNode): void\n  protected abstract visitDropType(node: DropTypeNode): void\n  protected abstract visitExplain(node: ExplainNode): void\n  protected abstract visitDefaultInsertValue(node: DefaultInsertValueNode): void\n  protected abstract visitAggregateFunction(node: AggregateFunctionNode): void\n  protected abstract visitOver(node: OverNode): void\n  protected abstract visitPartitionBy(node: PartitionByNode): void\n  protected abstract visitPartitionByItem(node: PartitionByItemNode): void\n  protected abstract visitSetOperation(node: SetOperationNode): void\n  protected abstract visitBinaryOperation(node: BinaryOperationNode): void\n  protected abstract visitUnaryOperation(node: UnaryOperationNode): void\n  protected abstract visitUsing(node: UsingNode): void\n  protected abstract visitFunction(node: FunctionNode): void\n  protected abstract visitCase(node: CaseNode): void\n  protected abstract visitWhen(node: WhenNode): void\n  protected abstract visitJSONReference(node: JSONReferenceNode): void\n  protected abstract visitJSONPath(node: JSONPathNode): void\n  protected abstract visitJSONPathLeg(node: JSONPathLegNode): void\n  protected abstract visitJSONOperatorChain(node: JSONOperatorChainNode): void\n  protected abstract visitTuple(node: TupleNode): void\n  protected abstract visitMergeQuery(node: MergeQueryNode): void\n  protected abstract visitMatched(node: MatchedNode): void\n  protected abstract visitAddIndex(node: AddIndexNode): void\n  protected abstract visitCast(node: CastNode): void\n  protected abstract visitFetch(node: FetchNode): void\n  protected abstract visitTop(node: TopNode): void\n  protected abstract visitOutput(node: OutputNode): void\n  protected abstract visitOrAction(node: OrActionNode): void\n  protected abstract visitCollate(node: CollateNode): void\n}\n"
  },
  {
    "path": "src/operation-node/operation-node.ts",
    "content": "export type OperationNodeKind =\n  | 'IdentifierNode'\n  | 'SchemableIdentifierNode'\n  | 'RawNode'\n  | 'SelectQueryNode'\n  | 'SelectionNode'\n  | 'ReferenceNode'\n  | 'ColumnNode'\n  | 'TableNode'\n  | 'AliasNode'\n  | 'FromNode'\n  | 'SelectAllNode'\n  | 'AndNode'\n  | 'OrNode'\n  | 'ParensNode'\n  | 'ValueNode'\n  | 'ValueListNode'\n  | 'PrimitiveValueListNode'\n  | 'JoinNode'\n  | 'OperatorNode'\n  | 'WhereNode'\n  | 'InsertQueryNode'\n  | 'DeleteQueryNode'\n  | 'ReturningNode'\n  | 'CreateTableNode'\n  | 'ColumnDefinitionNode'\n  | 'AddColumnNode'\n  | 'DropTableNode'\n  | 'DataTypeNode'\n  | 'OrderByNode'\n  | 'OrderByItemNode'\n  | 'GroupByNode'\n  | 'GroupByItemNode'\n  | 'UpdateQueryNode'\n  | 'ColumnUpdateNode'\n  | 'LimitNode'\n  | 'OffsetNode'\n  | 'OnConflictNode'\n  | 'OnDuplicateKeyNode'\n  | 'CreateIndexNode'\n  | 'DropIndexNode'\n  | 'ListNode'\n  | 'ReferencesNode'\n  | 'PrimaryKeyConstraintNode'\n  | 'UniqueConstraintNode'\n  | 'CheckConstraintNode'\n  | 'ForeignKeyConstraintNode'\n  | 'WithNode'\n  | 'CommonTableExpressionNode'\n  | 'HavingNode'\n  | 'CreateSchemaNode'\n  | 'DropSchemaNode'\n  | 'AlterTableNode'\n  | 'ModifyColumnNode'\n  | 'DropColumnNode'\n  | 'RenameColumnNode'\n  | 'AlterColumnNode'\n  | 'AddConstraintNode'\n  | 'DropConstraintNode'\n  | 'CreateViewNode'\n  | 'RefreshMaterializedViewNode'\n  | 'DropViewNode'\n  | 'GeneratedNode'\n  | 'DefaultValueNode'\n  | 'OnNode'\n  | 'ValuesNode'\n  | 'CommonTableExpressionNameNode'\n  | 'SelectModifierNode'\n  | 'CreateTypeNode'\n  | 'DropTypeNode'\n  | 'ExplainNode'\n  | 'DefaultInsertValueNode'\n  | 'AggregateFunctionNode'\n  | 'OverNode'\n  | 'PartitionByNode'\n  | 'PartitionByItemNode'\n  | 'SetOperationNode'\n  | 'BinaryOperationNode'\n  | 'UnaryOperationNode'\n  | 'UsingNode'\n  | 'FunctionNode'\n  | 'CaseNode'\n  | 'WhenNode'\n  | 'JSONReferenceNode'\n  | 'JSONPathNode'\n  | 'JSONPathLegNode'\n  | 'JSONOperatorChainNode'\n  | 'TupleNode'\n  | 'MergeQueryNode'\n  | 'MatchedNode'\n  | 'AddIndexNode'\n  | 'CastNode'\n  | 'FetchNode'\n  | 'TopNode'\n  | 'OutputNode'\n  | 'OrActionNode'\n  | 'CollateNode'\n  | 'RenameConstraintNode'\n\nexport interface OperationNode {\n  readonly kind: OperationNodeKind\n}\n"
  },
  {
    "path": "src/operation-node/operator-node.ts",
    "content": "import { freeze, isString } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport const COMPARISON_OPERATORS = [\n  '=',\n  '==',\n  '!=',\n  '<>',\n  '>',\n  '>=',\n  '<',\n  '<=',\n  'in',\n  'not in',\n  'is',\n  'is not',\n  'like',\n  'not like',\n  'match',\n  'ilike',\n  'not ilike',\n  '@>',\n  '<@',\n  '^@',\n  '&&',\n  '?',\n  '?&',\n  '?|',\n  '!<',\n  '!>',\n  '<=>',\n  '!~',\n  '~',\n  '~*',\n  '!~*',\n  '@@',\n  '@@@',\n  '!!',\n  '<->',\n  'regexp',\n  'is distinct from',\n  'is not distinct from',\n] as const\n\nexport const ARITHMETIC_OPERATORS = [\n  '+',\n  '-',\n  '*',\n  '/',\n  '%',\n  '^',\n  '&',\n  '|',\n  '#',\n  '<<',\n  '>>',\n] as const\n\nexport const JSON_OPERATORS = ['->', '->>'] as const\n\nexport const BINARY_OPERATORS = [\n  ...COMPARISON_OPERATORS,\n  ...ARITHMETIC_OPERATORS,\n  '&&',\n  '||',\n] as const\n\nexport const UNARY_FILTER_OPERATORS = ['exists', 'not exists'] as const\nexport const UNARY_OPERATORS = ['not', '-', ...UNARY_FILTER_OPERATORS] as const\nexport const OPERATORS = [\n  ...BINARY_OPERATORS,\n  ...JSON_OPERATORS,\n  ...UNARY_OPERATORS,\n  'between',\n  'between symmetric',\n] as const\n\nexport type ComparisonOperator = (typeof COMPARISON_OPERATORS)[number]\nexport type ArithmeticOperator = (typeof ARITHMETIC_OPERATORS)[number]\nexport type JSONOperator = (typeof JSON_OPERATORS)[number]\nexport type JSONOperatorWith$ = JSONOperator | `${JSONOperator}$`\nexport type BinaryOperator = (typeof BINARY_OPERATORS)[number]\nexport type UnaryOperator = (typeof UNARY_OPERATORS)[number]\nexport type UnaryFilterOperator = (typeof UNARY_FILTER_OPERATORS)[number]\nexport type Operator = (typeof OPERATORS)[number]\n\nexport interface OperatorNode extends OperationNode {\n  readonly kind: 'OperatorNode'\n  readonly operator: Operator\n}\n\ntype OperatorNodeFactory = Readonly<{\n  is(node: OperationNode): node is OperatorNode\n  create(operator: Operator): Readonly<OperatorNode>\n}>\n\n/**\n * @internal\n */\nexport const OperatorNode: OperatorNodeFactory = freeze<OperatorNodeFactory>({\n  is(node): node is OperatorNode {\n    return node.kind === 'OperatorNode'\n  },\n\n  create(operator) {\n    return freeze({\n      kind: 'OperatorNode',\n      operator,\n    })\n  },\n})\n\nexport function isOperator(op: unknown): op is Operator {\n  return isString(op) && OPERATORS.includes(op as Operator)\n}\n\nexport function isBinaryOperator(op: unknown): op is BinaryOperator {\n  return isString(op) && BINARY_OPERATORS.includes(op as BinaryOperator)\n}\n\nexport function isComparisonOperator(op: unknown): op is ComparisonOperator {\n  return isString(op) && COMPARISON_OPERATORS.includes(op as ComparisonOperator)\n}\n\nexport function isArithmeticOperator(op: unknown): op is ArithmeticOperator {\n  return isString(op) && ARITHMETIC_OPERATORS.includes(op as ArithmeticOperator)\n}\n\nexport function isJSONOperator(op: unknown): op is JSONOperator {\n  return isString(op) && JSON_OPERATORS.includes(op as JSONOperator)\n}\n"
  },
  {
    "path": "src/operation-node/or-action-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface OrActionNode extends OperationNode {\n  readonly kind: 'OrActionNode'\n  readonly action: string\n}\n\ntype OrActionNodeFactory = Readonly<{\n  is(node: OperationNode): node is OrActionNode\n  create(action: string): Readonly<OrActionNode>\n}>\n\n/**\n * @internal\n */\nexport const OrActionNode: OrActionNodeFactory = freeze<OrActionNodeFactory>({\n  is(node): node is OrActionNode {\n    return node.kind === 'OrActionNode'\n  },\n\n  create(action) {\n    return freeze({\n      kind: 'OrActionNode',\n      action,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/or-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface OrNode extends OperationNode {\n  readonly kind: 'OrNode'\n  readonly left: OperationNode\n  readonly right: OperationNode\n}\n\ntype OrNodeFactory = Readonly<{\n  is(node: OperationNode): node is OrNode\n  create(left: OperationNode, right: OperationNode): Readonly<OrNode>\n}>\n\n/**\n * @internal\n */\nexport const OrNode: OrNodeFactory = freeze<OrNodeFactory>({\n  is(node): node is OrNode {\n    return node.kind === 'OrNode'\n  },\n\n  create(left, right) {\n    return freeze({\n      kind: 'OrNode',\n      left,\n      right,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/order-by-item-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { CollateNode } from './collate-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport type OrderByItemNodeProps = Omit<OrderByItemNode, 'kind' | 'orderBy'>\n\nexport interface OrderByItemNode extends OperationNode {\n  readonly kind: 'OrderByItemNode'\n  readonly orderBy: OperationNode\n  readonly direction?: OperationNode\n  readonly nulls?: 'first' | 'last'\n  readonly collation?: CollateNode\n}\n\ntype OrderByItemNodeFactory = Readonly<{\n  is(node: OperationNode): node is OrderByItemNode\n  create(\n    orderBy: OperationNode,\n    direction?: OperationNode,\n  ): Readonly<OrderByItemNode>\n  cloneWith(\n    node: OrderByItemNode,\n    props: OrderByItemNodeProps,\n  ): Readonly<OrderByItemNode>\n}>\n\n/**\n * @internal\n */\nexport const OrderByItemNode: OrderByItemNodeFactory =\n  freeze<OrderByItemNodeFactory>({\n    is(node): node is OrderByItemNode {\n      return node.kind === 'OrderByItemNode'\n    },\n\n    create(orderBy, direction?) {\n      return freeze({\n        kind: 'OrderByItemNode',\n        orderBy,\n        direction,\n      })\n    },\n\n    cloneWith(node, props) {\n      return freeze({\n        ...node,\n        ...props,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/order-by-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { OrderByItemNode } from './order-by-item-node.js'\n\nexport interface OrderByNode extends OperationNode {\n  readonly kind: 'OrderByNode'\n  readonly items: ReadonlyArray<OrderByItemNode>\n}\n\ntype OrderByNodeFactory = Readonly<{\n  is(node: OperationNode): node is OrderByNode\n  create(items: ReadonlyArray<OrderByItemNode>): Readonly<OrderByNode>\n  cloneWithItems(\n    orderBy: OrderByNode,\n    items: ReadonlyArray<OrderByItemNode>,\n  ): Readonly<OrderByNode>\n}>\n\n/**\n * @internal\n */\nexport const OrderByNode: OrderByNodeFactory = freeze<OrderByNodeFactory>({\n  is(node): node is OrderByNode {\n    return node.kind === 'OrderByNode'\n  },\n\n  create(items) {\n    return freeze({\n      kind: 'OrderByNode',\n      items: freeze([...items]),\n    })\n  },\n\n  cloneWithItems(orderBy, items) {\n    return freeze({\n      ...orderBy,\n      items: freeze([...orderBy.items, ...items]),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/output-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface OutputNode extends OperationNode {\n  readonly kind: 'OutputNode'\n  readonly selections: ReadonlyArray<OperationNode>\n}\n\ntype OutputNodeFactory = Readonly<{\n  is(node: OperationNode): node is OutputNode\n  create(selections: ReadonlyArray<OperationNode>): Readonly<OutputNode>\n  cloneWithSelections(\n    output: OutputNode,\n    selections: ReadonlyArray<OperationNode>,\n  ): Readonly<OutputNode>\n}>\n\n/**\n * @internal\n */\nexport const OutputNode: OutputNodeFactory = freeze<OutputNodeFactory>({\n  is(node): node is OutputNode {\n    return node.kind === 'OutputNode'\n  },\n\n  create(selections) {\n    return freeze({\n      kind: 'OutputNode',\n      selections: freeze(selections),\n    })\n  },\n\n  cloneWithSelections(output, selections) {\n    return freeze({\n      ...output,\n      selections: output.selections\n        ? freeze([...output.selections, ...selections])\n        : freeze(selections),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/over-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { OrderByItemNode } from './order-by-item-node.js'\nimport { OrderByNode } from './order-by-node.js'\nimport type { PartitionByItemNode } from './partition-by-item-node.js'\nimport { PartitionByNode } from './partition-by-node.js'\n\nexport interface OverNode extends OperationNode {\n  readonly kind: 'OverNode'\n  readonly orderBy?: OrderByNode\n  readonly partitionBy?: PartitionByNode\n}\n\ntype OverNodeFactory = Readonly<{\n  is(node: OperationNode): node is OverNode\n  create(): Readonly<OverNode>\n  cloneWithOrderByItems(\n    overNode: OverNode,\n    items: ReadonlyArray<OrderByItemNode>,\n  ): Readonly<OverNode>\n  cloneWithPartitionByItems(\n    overNode: OverNode,\n    items: ReadonlyArray<PartitionByItemNode>,\n  ): Readonly<OverNode>\n}>\n\n/**\n * @internal\n */\nexport const OverNode: OverNodeFactory = freeze<OverNodeFactory>({\n  is(node): node is OverNode {\n    return node.kind === 'OverNode'\n  },\n\n  create() {\n    return freeze({\n      kind: 'OverNode',\n    })\n  },\n\n  cloneWithOrderByItems(overNode, items) {\n    return freeze({\n      ...overNode,\n      orderBy: overNode.orderBy\n        ? OrderByNode.cloneWithItems(overNode.orderBy, items)\n        : OrderByNode.create(items),\n    })\n  },\n\n  cloneWithPartitionByItems(overNode, items) {\n    return freeze({\n      ...overNode,\n      partitionBy: overNode.partitionBy\n        ? PartitionByNode.cloneWithItems(overNode.partitionBy, items)\n        : PartitionByNode.create(items),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/parens-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport interface ParensNode extends OperationNode {\n  readonly kind: 'ParensNode'\n  readonly node: OperationNode\n}\n\ntype ParensNodeFactory = Readonly<{\n  is(node: OperationNode): node is ParensNode\n  create(node: OperationNode): Readonly<ParensNode>\n}>\n\n/**\n * @internal\n */\nexport const ParensNode: ParensNodeFactory = freeze<ParensNodeFactory>({\n  is(node): node is ParensNode {\n    return node.kind === 'ParensNode'\n  },\n\n  create(node) {\n    return freeze({\n      kind: 'ParensNode',\n      node,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/partition-by-item-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { SimpleReferenceExpressionNode } from './simple-reference-expression-node.js'\n\nexport interface PartitionByItemNode extends OperationNode {\n  readonly kind: 'PartitionByItemNode'\n  readonly partitionBy: SimpleReferenceExpressionNode\n}\n\ntype PartitionByItemNodeFactory = Readonly<{\n  is(node: OperationNode): node is PartitionByItemNode\n  create(\n    partitionBy: SimpleReferenceExpressionNode,\n  ): Readonly<PartitionByItemNode>\n}>\n\n/**\n * @internal\n */\nexport const PartitionByItemNode: PartitionByItemNodeFactory =\n  freeze<PartitionByItemNodeFactory>({\n    is(node): node is PartitionByItemNode {\n      return node.kind === 'PartitionByItemNode'\n    },\n\n    create(partitionBy) {\n      return freeze({\n        kind: 'PartitionByItemNode',\n        partitionBy,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/partition-by-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { PartitionByItemNode } from './partition-by-item-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface PartitionByNode extends OperationNode {\n  readonly kind: 'PartitionByNode'\n  readonly items: ReadonlyArray<PartitionByItemNode>\n}\n\ntype PartitionByNodeFactory = Readonly<{\n  is(node: OperationNode): node is PartitionByNode\n  create(items: ReadonlyArray<PartitionByItemNode>): Readonly<PartitionByNode>\n  cloneWithItems(\n    partitionBy: PartitionByNode,\n    items: ReadonlyArray<PartitionByItemNode>,\n  ): Readonly<PartitionByNode>\n}>\n\n/**\n * @internal\n */\nexport const PartitionByNode: PartitionByNodeFactory =\n  freeze<PartitionByNodeFactory>({\n    is(node): node is PartitionByNode {\n      return node.kind === 'PartitionByNode'\n    },\n\n    create(items) {\n      return freeze({\n        kind: 'PartitionByNode',\n        items: freeze(items),\n      })\n    },\n\n    cloneWithItems(partitionBy, items) {\n      return freeze({\n        ...partitionBy,\n        items: freeze([...partitionBy.items, ...items]),\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/primary-key-constraint-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { ColumnNode } from './column-node.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface PrimaryKeyConstraintNode extends OperationNode {\n  readonly kind: 'PrimaryKeyConstraintNode'\n  readonly columns: ReadonlyArray<ColumnNode>\n  readonly name?: IdentifierNode\n  readonly deferrable?: boolean\n  readonly initiallyDeferred?: boolean\n}\n\nexport type PrimaryKeyConstraintNodeProps = Omit<\n  Partial<PrimaryKeyConstraintNode>,\n  'kind'\n>\n\ntype PrimaryKeyConstraintNodeFactory = Readonly<{\n  is(node: OperationNode): node is PrimaryKeyConstraintNode\n  create(\n    columns: string[],\n    constraintName?: string,\n  ): Readonly<PrimaryKeyConstraintNode>\n  cloneWith(\n    node: PrimaryKeyConstraintNode,\n    props: PrimaryKeyConstraintNodeProps,\n  ): Readonly<PrimaryKeyConstraintNode>\n}>\n\n/**\n * @internal\n */\nexport const PrimaryKeyConstraintNode: PrimaryKeyConstraintNodeFactory =\n  freeze<PrimaryKeyConstraintNodeFactory>({\n    is(node): node is PrimaryKeyConstraintNode {\n      return node.kind === 'PrimaryKeyConstraintNode'\n    },\n\n    create(columns, constraintName?) {\n      return freeze({\n        kind: 'PrimaryKeyConstraintNode',\n        columns: freeze(columns.map(ColumnNode.create)),\n        name: constraintName\n          ? IdentifierNode.create(constraintName)\n          : undefined,\n      })\n    },\n\n    cloneWith(node, props) {\n      return freeze({ ...node, ...props })\n    },\n  })\n\n/**\n * Backwards compatibility for a typo in the codebase.\n *\n * @deprecated Use {@link PrimaryKeyConstraintNode} instead.\n */\nexport const PrimaryConstraintNode = PrimaryKeyConstraintNode\n"
  },
  {
    "path": "src/operation-node/primitive-value-list-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\n/**\n * This node is basically just a performance optimization over the normal ValueListNode.\n * The queries often contain large arrays of primitive values (for example in a `where in` list)\n * and we don't want to create a ValueNode for each item in those lists.\n */\nexport interface PrimitiveValueListNode extends OperationNode {\n  readonly kind: 'PrimitiveValueListNode'\n  readonly values: ReadonlyArray<unknown>\n}\n\ntype PrimitiveValueListNodeFactory = Readonly<{\n  is(node: OperationNode): node is PrimitiveValueListNode\n  create(values: ReadonlyArray<unknown>): Readonly<PrimitiveValueListNode>\n}>\n\n/**\n * @internal\n */\nexport const PrimitiveValueListNode: PrimitiveValueListNodeFactory =\n  freeze<PrimitiveValueListNodeFactory>({\n    is(node): node is PrimitiveValueListNode {\n      return node.kind === 'PrimitiveValueListNode'\n    },\n\n    create(values) {\n      return freeze({\n        kind: 'PrimitiveValueListNode',\n        values: freeze([...values]),\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/query-node.ts",
    "content": "import { InsertQueryNode } from './insert-query-node.js'\nimport { SelectQueryNode } from './select-query-node.js'\nimport { UpdateQueryNode } from './update-query-node.js'\nimport { DeleteQueryNode } from './delete-query-node.js'\nimport { WhereNode } from './where-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { JoinNode } from './join-node.js'\nimport type { SelectionNode } from './selection-node.js'\nimport { ReturningNode } from './returning-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport { ExplainNode } from './explain-node.js'\nimport type { ExplainFormat } from '../util/explainable.js'\nimport type { Expression } from '../expression/expression.js'\nimport { MergeQueryNode } from './merge-query-node.js'\nimport type { TopNode } from './top-node.js'\nimport { OutputNode } from './output-node.js'\nimport { OrderByNode } from './order-by-node.js'\nimport type { OrderByItemNode } from './order-by-item-node.js'\n\nexport type QueryNode =\n  | SelectQueryNode\n  | InsertQueryNode\n  | UpdateQueryNode\n  | DeleteQueryNode\n  | MergeQueryNode\n\ntype HasJoins = { joins?: ReadonlyArray<JoinNode> }\ntype HasWhere = { where?: WhereNode }\ntype HasReturning = { returning?: ReturningNode }\ntype HasExplain = { explain?: ExplainNode }\ntype HasTop = { top?: TopNode }\ntype HasOutput = { output?: OutputNode }\ntype HasEndModifiers = { endModifiers?: ReadonlyArray<OperationNode> }\ntype HasOrderBy = { orderBy?: OrderByNode }\n\ntype QueryNodeFactory = Readonly<{\n  is(node: OperationNode): node is QueryNode\n  cloneWithEndModifier<T extends HasEndModifiers>(\n    node: T,\n    modifier: OperationNode,\n  ): Readonly<T>\n  cloneWithWhere<T extends HasWhere>(\n    node: T,\n    operation: OperationNode,\n  ): Readonly<T>\n  cloneWithJoin<T extends HasJoins>(node: T, join: JoinNode): Readonly<T>\n  cloneWithReturning<T extends HasReturning>(\n    node: T,\n    selections: ReadonlyArray<SelectionNode>,\n  ): Readonly<T>\n  cloneWithoutReturning<T extends HasReturning>(node: T): Readonly<T>\n  cloneWithoutWhere<T extends HasWhere>(node: T): Readonly<T>\n  cloneWithExplain<T extends HasExplain>(\n    node: T,\n    format: ExplainFormat | undefined,\n    options: Expression<any> | undefined,\n  ): Readonly<T>\n  cloneWithTop<T extends HasTop>(node: T, top: TopNode): Readonly<T>\n  cloneWithOutput<T extends HasOutput>(\n    node: T,\n    selections: ReadonlyArray<SelectionNode>,\n  ): Readonly<T>\n  cloneWithOrderByItems<T extends HasOrderBy>(\n    node: T,\n    items: ReadonlyArray<OrderByItemNode>,\n  ): Readonly<T>\n  cloneWithoutOrderBy<T extends HasOrderBy>(node: T): Readonly<T>\n}>\n\n/**\n * @internal\n */\nexport const QueryNode: QueryNodeFactory = freeze<QueryNodeFactory>({\n  is(node): node is QueryNode {\n    return (\n      SelectQueryNode.is(node) ||\n      InsertQueryNode.is(node) ||\n      UpdateQueryNode.is(node) ||\n      DeleteQueryNode.is(node) ||\n      MergeQueryNode.is(node)\n    )\n  },\n\n  cloneWithEndModifier(node, modifier) {\n    return freeze({\n      ...node,\n      endModifiers: node.endModifiers\n        ? freeze([...node.endModifiers, modifier])\n        : freeze([modifier]),\n    })\n  },\n\n  cloneWithWhere(node, operation) {\n    return freeze({\n      ...node,\n      where: node.where\n        ? WhereNode.cloneWithOperation(node.where, 'And', operation)\n        : WhereNode.create(operation),\n    })\n  },\n\n  cloneWithJoin(node, join) {\n    return freeze({\n      ...node,\n      joins: node.joins ? freeze([...node.joins, join]) : freeze([join]),\n    })\n  },\n\n  cloneWithReturning(node, selections) {\n    return freeze({\n      ...node,\n      returning: node.returning\n        ? ReturningNode.cloneWithSelections(node.returning, selections)\n        : ReturningNode.create(selections),\n    })\n  },\n\n  cloneWithoutReturning(node) {\n    return freeze({\n      ...node,\n      returning: undefined,\n    })\n  },\n\n  cloneWithoutWhere(node) {\n    return freeze({\n      ...node,\n      where: undefined,\n    })\n  },\n\n  cloneWithExplain(node, format, options) {\n    return freeze({\n      ...node,\n      explain: ExplainNode.create(format, options?.toOperationNode()),\n    })\n  },\n\n  cloneWithTop(node, top) {\n    return freeze({\n      ...node,\n      top,\n    })\n  },\n\n  cloneWithOutput(node, selections) {\n    return freeze({\n      ...node,\n      output: node.output\n        ? OutputNode.cloneWithSelections(node.output, selections)\n        : OutputNode.create(selections),\n    })\n  },\n\n  cloneWithOrderByItems(node, items) {\n    return freeze({\n      ...node,\n      orderBy: node.orderBy\n        ? OrderByNode.cloneWithItems(node.orderBy, items)\n        : OrderByNode.create(items),\n    })\n  },\n\n  cloneWithoutOrderBy(node) {\n    return freeze({\n      ...node,\n      orderBy: undefined,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/raw-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface RawNode extends OperationNode {\n  readonly kind: 'RawNode'\n  readonly sqlFragments: ReadonlyArray<string>\n  readonly parameters: ReadonlyArray<OperationNode>\n}\n\ntype RawNodeFactory = Readonly<{\n  is(node: OperationNode): node is RawNode\n  create(\n    sqlFragments: ReadonlyArray<string>,\n    parameters: ReadonlyArray<OperationNode>,\n  ): Readonly<RawNode>\n  createWithSql(sql: string): Readonly<RawNode>\n  createWithChild(child: OperationNode): Readonly<RawNode>\n  createWithChildren(children: ReadonlyArray<OperationNode>): Readonly<RawNode>\n}>\n\n/**\n * @internal\n */\nexport const RawNode: RawNodeFactory = freeze<RawNodeFactory>({\n  is(node): node is RawNode {\n    return node.kind === 'RawNode'\n  },\n\n  create(sqlFragments, parameters) {\n    return freeze({\n      kind: 'RawNode',\n      sqlFragments: freeze(sqlFragments),\n      parameters: freeze(parameters),\n    })\n  },\n\n  createWithSql(sql) {\n    return RawNode.create([sql], [])\n  },\n\n  createWithChild(child) {\n    return RawNode.create(['', ''], [child])\n  },\n\n  createWithChildren(children) {\n    return RawNode.create(new Array(children.length + 1).fill(''), children)\n  },\n})\n"
  },
  {
    "path": "src/operation-node/reference-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport type { ColumnNode } from './column-node.js'\nimport type { TableNode } from './table-node.js'\nimport { SelectAllNode } from './select-all-node.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport interface ReferenceNode extends OperationNode {\n  readonly kind: 'ReferenceNode'\n  readonly column: ColumnNode | SelectAllNode\n  readonly table?: TableNode\n}\n\ntype ReferenceNodeFactory = Readonly<{\n  is(node: OperationNode): node is ReferenceNode\n  create(column: ColumnNode, table?: TableNode): Readonly<ReferenceNode>\n  createSelectAll(table: TableNode): Readonly<ReferenceNode>\n}>\n\n/**\n * @internal\n */\nexport const ReferenceNode: ReferenceNodeFactory = freeze<ReferenceNodeFactory>(\n  {\n    is(node): node is ReferenceNode {\n      return node.kind === 'ReferenceNode'\n    },\n\n    create(column, table?) {\n      return freeze({\n        kind: 'ReferenceNode',\n        table,\n        column,\n      })\n    },\n\n    createSelectAll(table) {\n      return freeze({\n        kind: 'ReferenceNode',\n        table,\n        column: SelectAllNode.create(),\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/operation-node/references-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport type { ColumnNode } from './column-node.js'\nimport type { TableNode } from './table-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { ArrayItemType } from '../util/type-utils.js'\n\nexport const ON_MODIFY_FOREIGN_ACTIONS = [\n  'no action',\n  'restrict',\n  'cascade',\n  'set null',\n  'set default',\n] as const\n\nexport type OnModifyForeignAction = ArrayItemType<\n  typeof ON_MODIFY_FOREIGN_ACTIONS\n>\n\nexport interface ReferencesNode extends OperationNode {\n  readonly kind: 'ReferencesNode'\n  readonly table: TableNode\n  readonly columns: ReadonlyArray<ColumnNode>\n  readonly onDelete?: OnModifyForeignAction\n  readonly onUpdate?: OnModifyForeignAction\n}\n\ntype ReferencesNodeFactory = Readonly<{\n  is(node: OperationNode): node is ReferencesNode\n  create(\n    table: TableNode,\n    columns: ReadonlyArray<ColumnNode>,\n  ): Readonly<ReferencesNode>\n  cloneWithOnDelete(\n    references: ReferencesNode,\n    onDelete: OnModifyForeignAction,\n  ): Readonly<ReferencesNode>\n  cloneWithOnUpdate(\n    references: ReferencesNode,\n    onUpdate: OnModifyForeignAction,\n  ): Readonly<ReferencesNode>\n}>\n\n/**\n * @internal\n */\nexport const ReferencesNode: ReferencesNodeFactory =\n  freeze<ReferencesNodeFactory>({\n    is(node): node is ReferencesNode {\n      return node.kind === 'ReferencesNode'\n    },\n\n    create(table, columns) {\n      return freeze({\n        kind: 'ReferencesNode',\n        table,\n        columns: freeze([...columns]),\n      })\n    },\n\n    cloneWithOnDelete(references, onDelete) {\n      return freeze({\n        ...references,\n        onDelete,\n      })\n    },\n\n    cloneWithOnUpdate(references, onUpdate) {\n      return freeze({\n        ...references,\n        onUpdate,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/refresh-materialized-view-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport { SchemableIdentifierNode } from './schemable-identifier-node.js'\n\nexport type RefreshMaterializedViewNodeParams = Omit<\n  Partial<RefreshMaterializedViewNode>,\n  'kind' | 'name'\n>\n\nexport interface RefreshMaterializedViewNode extends OperationNode {\n  readonly kind: 'RefreshMaterializedViewNode'\n  readonly name: SchemableIdentifierNode\n  readonly concurrently?: boolean\n  readonly withNoData?: boolean\n}\n\ntype RefreshMaterializedViewNodeFactory = Readonly<{\n  is(node: OperationNode): node is RefreshMaterializedViewNode\n  create(name: string): Readonly<RefreshMaterializedViewNode>\n  cloneWith(\n    createView: RefreshMaterializedViewNode,\n    params: RefreshMaterializedViewNodeParams,\n  ): Readonly<RefreshMaterializedViewNode>\n}>\n\n/**\n * @internal\n */\nexport const RefreshMaterializedViewNode: RefreshMaterializedViewNodeFactory =\n  freeze<RefreshMaterializedViewNodeFactory>({\n    is(node): node is RefreshMaterializedViewNode {\n      return node.kind === 'RefreshMaterializedViewNode'\n    },\n\n    create(name) {\n      return freeze({\n        kind: 'RefreshMaterializedViewNode',\n        name: SchemableIdentifierNode.create(name),\n      })\n    },\n\n    cloneWith(createView, params) {\n      return freeze({\n        ...createView,\n        ...params,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/rename-column-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport { ColumnNode } from './column-node.js'\n\nexport interface RenameColumnNode extends OperationNode {\n  readonly kind: 'RenameColumnNode'\n  readonly column: ColumnNode\n  readonly renameTo: ColumnNode\n}\n\ntype RenameColumnNodeFactory = Readonly<{\n  is(node: OperationNode): node is RenameColumnNode\n  create(column: string, newColumn: string): Readonly<RenameColumnNode>\n}>\n\n/**\n * @internal\n */\nexport const RenameColumnNode: RenameColumnNodeFactory =\n  freeze<RenameColumnNodeFactory>({\n    is(node): node is RenameColumnNode {\n      return node.kind === 'RenameColumnNode'\n    },\n\n    create(column, newColumn) {\n      return freeze({\n        kind: 'RenameColumnNode',\n        column: ColumnNode.create(column),\n        renameTo: ColumnNode.create(newColumn),\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/rename-constraint-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\n\nexport interface RenameConstraintNode extends OperationNode {\n  readonly kind: 'RenameConstraintNode'\n  readonly oldName: IdentifierNode\n  readonly newName: IdentifierNode\n}\n\ntype RenameConstraintNodeFactory = Readonly<{\n  is(node: OperationNode): node is RenameConstraintNode\n  create(oldName: string, newName: string): Readonly<RenameConstraintNode>\n}>\n\n/**\n * @internal\n */\nexport const RenameConstraintNode: RenameConstraintNodeFactory =\n  freeze<RenameConstraintNodeFactory>({\n    is(node): node is RenameConstraintNode {\n      return node.kind === 'RenameConstraintNode'\n    },\n\n    create(oldName, newName) {\n      return freeze({\n        kind: 'RenameConstraintNode',\n        oldName: IdentifierNode.create(oldName),\n        newName: IdentifierNode.create(newName),\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/returning-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { SelectionNode } from './selection-node.js'\n\nexport interface ReturningNode extends OperationNode {\n  readonly kind: 'ReturningNode'\n  readonly selections: ReadonlyArray<SelectionNode>\n}\n\ntype ReturningNodeFactory = Readonly<{\n  is(node: OperationNode): node is ReturningNode\n  create(selections: ReadonlyArray<SelectionNode>): Readonly<ReturningNode>\n  cloneWithSelections(\n    returning: ReturningNode,\n    selections: ReadonlyArray<SelectionNode>,\n  ): Readonly<ReturningNode>\n}>\n\n/**\n * @internal\n */\nexport const ReturningNode: ReturningNodeFactory = freeze<ReturningNodeFactory>(\n  {\n    is(node): node is ReturningNode {\n      return node.kind === 'ReturningNode'\n    },\n\n    create(selections) {\n      return freeze({\n        kind: 'ReturningNode',\n        selections: freeze(selections),\n      })\n    },\n\n    cloneWithSelections(returning, selections) {\n      return freeze({\n        ...returning,\n        selections: returning.selections\n          ? freeze([...returning.selections, ...selections])\n          : freeze(selections),\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/operation-node/schemable-identifier-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface SchemableIdentifierNode extends OperationNode {\n  readonly kind: 'SchemableIdentifierNode'\n  readonly schema?: IdentifierNode\n  readonly identifier: IdentifierNode\n}\n\ntype SchemableIdentifierNodeFactory = Readonly<{\n  is(node: OperationNode): node is SchemableIdentifierNode\n  create(identifier: string): Readonly<SchemableIdentifierNode>\n  createWithSchema(\n    schema: string,\n    identifier: string,\n  ): Readonly<SchemableIdentifierNode>\n}>\n\n/**\n * @internal\n */\nexport const SchemableIdentifierNode: SchemableIdentifierNodeFactory =\n  freeze<SchemableIdentifierNodeFactory>({\n    is(node): node is SchemableIdentifierNode {\n      return node.kind === 'SchemableIdentifierNode'\n    },\n\n    create(identifier) {\n      return freeze({\n        kind: 'SchemableIdentifierNode',\n        identifier: IdentifierNode.create(identifier),\n      })\n    },\n\n    createWithSchema(schema, identifier) {\n      return freeze({\n        kind: 'SchemableIdentifierNode',\n        schema: IdentifierNode.create(schema),\n        identifier: IdentifierNode.create(identifier),\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/select-all-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface SelectAllNode extends OperationNode {\n  readonly kind: 'SelectAllNode'\n}\n\ntype SelectAllNodeFactory = Readonly<{\n  is(node: OperationNode): node is SelectAllNode\n  create(): Readonly<SelectAllNode>\n}>\n\n/**\n * @internal\n */\nexport const SelectAllNode: SelectAllNodeFactory = freeze<SelectAllNodeFactory>(\n  {\n    is(node): node is SelectAllNode {\n      return node.kind === 'SelectAllNode'\n    },\n\n    create() {\n      return freeze({\n        kind: 'SelectAllNode',\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/operation-node/select-modifier-node.ts",
    "content": "import type { OperationNode } from './operation-node.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport type SelectModifier =\n  | 'ForUpdate'\n  | 'ForNoKeyUpdate'\n  | 'ForShare'\n  | 'ForKeyShare'\n  | 'NoWait'\n  | 'SkipLocked'\n  | 'Distinct'\n\nexport interface SelectModifierNode extends OperationNode {\n  readonly kind: 'SelectModifierNode'\n  readonly modifier?: SelectModifier\n  readonly rawModifier?: OperationNode\n  readonly of?: ReadonlyArray<OperationNode>\n}\n\ntype SelectModifierNodeFactory = Readonly<{\n  is(node: OperationNode): node is SelectModifierNode\n  create(\n    modifier: SelectModifier,\n    of?: ReadonlyArray<OperationNode>,\n  ): Readonly<SelectModifierNode>\n  createWithExpression(modifier: OperationNode): Readonly<SelectModifierNode>\n}>\n\n/**\n * @internal\n */\nexport const SelectModifierNode: SelectModifierNodeFactory =\n  freeze<SelectModifierNodeFactory>({\n    is(node): node is SelectModifierNode {\n      return node.kind === 'SelectModifierNode'\n    },\n\n    create(modifier, of?) {\n      return freeze({\n        kind: 'SelectModifierNode',\n        modifier,\n        of,\n      })\n    },\n\n    createWithExpression(modifier) {\n      return freeze({\n        kind: 'SelectModifierNode',\n        rawModifier: modifier,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/select-query-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { FromNode } from './from-node.js'\nimport type { GroupByItemNode } from './group-by-item-node.js'\nimport { GroupByNode } from './group-by-node.js'\nimport { HavingNode } from './having-node.js'\nimport type { JoinNode } from './join-node.js'\nimport type { LimitNode } from './limit-node.js'\nimport type { OffsetNode } from './offset-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { OrderByItemNode } from './order-by-item-node.js'\nimport type { OrderByNode } from './order-by-node.js'\nimport type { SelectionNode } from './selection-node.js'\nimport type { WhereNode } from './where-node.js'\nimport type { WithNode } from './with-node.js'\nimport type { SelectModifierNode } from './select-modifier-node.js'\nimport type { ExplainNode } from './explain-node.js'\nimport type { SetOperationNode } from './set-operation-node.js'\nimport type { FetchNode } from './fetch-node.js'\nimport type { TopNode } from './top-node.js'\nimport { QueryNode } from './query-node.js'\n\nexport interface SelectQueryNode extends OperationNode {\n  readonly kind: 'SelectQueryNode'\n  readonly from?: FromNode\n  readonly selections?: ReadonlyArray<SelectionNode>\n  readonly distinctOn?: ReadonlyArray<OperationNode>\n  readonly joins?: ReadonlyArray<JoinNode>\n  readonly groupBy?: GroupByNode\n  readonly orderBy?: OrderByNode\n  readonly where?: WhereNode\n  readonly frontModifiers?: ReadonlyArray<SelectModifierNode>\n  readonly endModifiers?: ReadonlyArray<SelectModifierNode>\n  readonly limit?: LimitNode\n  readonly offset?: OffsetNode\n  readonly with?: WithNode\n  readonly having?: HavingNode\n  readonly explain?: ExplainNode\n  readonly setOperations?: ReadonlyArray<SetOperationNode>\n  readonly fetch?: FetchNode\n  readonly top?: TopNode\n}\n\ntype SelectQueryNodeFactory = Readonly<{\n  is(node: OperationNode): node is SelectQueryNode\n  create(withNode?: WithNode): Readonly<SelectQueryNode>\n  createFrom(\n    fromItems: ReadonlyArray<OperationNode>,\n    withNode?: WithNode,\n  ): Readonly<SelectQueryNode>\n  cloneWithSelections(\n    select: SelectQueryNode,\n    selections: ReadonlyArray<SelectionNode>,\n  ): Readonly<SelectQueryNode>\n  cloneWithDistinctOn(\n    select: SelectQueryNode,\n    expressions: ReadonlyArray<OperationNode>,\n  ): Readonly<SelectQueryNode>\n  cloneWithFrontModifier(\n    select: SelectQueryNode,\n    modifier: SelectModifierNode,\n  ): Readonly<SelectQueryNode>\n  cloneWithOrderByItems(\n    node: SelectQueryNode,\n    items: ReadonlyArray<OrderByItemNode>,\n  ): Readonly<SelectQueryNode>\n  cloneWithGroupByItems(\n    selectNode: SelectQueryNode,\n    items: ReadonlyArray<GroupByItemNode>,\n  ): Readonly<SelectQueryNode>\n  cloneWithLimit(\n    selectNode: SelectQueryNode,\n    limit: LimitNode,\n  ): Readonly<SelectQueryNode>\n  cloneWithOffset(\n    selectNode: SelectQueryNode,\n    offset: OffsetNode,\n  ): Readonly<SelectQueryNode>\n  cloneWithFetch(\n    selectNode: SelectQueryNode,\n    fetch: FetchNode,\n  ): Readonly<SelectQueryNode>\n  cloneWithHaving(\n    selectNode: SelectQueryNode,\n    operation: OperationNode,\n  ): Readonly<SelectQueryNode>\n  cloneWithSetOperations(\n    selectNode: SelectQueryNode,\n    setOperations: ReadonlyArray<SetOperationNode>,\n  ): Readonly<SelectQueryNode>\n  cloneWithoutSelections(select: SelectQueryNode): Readonly<SelectQueryNode>\n  cloneWithoutLimit(select: SelectQueryNode): Readonly<SelectQueryNode>\n  cloneWithoutOffset(select: SelectQueryNode): Readonly<SelectQueryNode>\n  cloneWithoutOrderBy(node: SelectQueryNode): Readonly<SelectQueryNode>\n  cloneWithoutGroupBy(select: SelectQueryNode): Readonly<SelectQueryNode>\n}>\n\n/**\n * @internal\n */\nexport const SelectQueryNode: SelectQueryNodeFactory =\n  freeze<SelectQueryNodeFactory>({\n    is(node): node is SelectQueryNode {\n      return node.kind === 'SelectQueryNode'\n    },\n\n    create(withNode?) {\n      return freeze({\n        kind: 'SelectQueryNode',\n        ...(withNode && { with: withNode }),\n      })\n    },\n\n    createFrom(fromItems, withNode?) {\n      return freeze({\n        kind: 'SelectQueryNode',\n        from: FromNode.create(fromItems),\n        ...(withNode && { with: withNode }),\n      })\n    },\n\n    cloneWithSelections(select, selections) {\n      return freeze({\n        ...select,\n        selections: select.selections\n          ? freeze([...select.selections, ...selections])\n          : freeze(selections),\n      })\n    },\n\n    cloneWithDistinctOn(select, expressions) {\n      return freeze({\n        ...select,\n        distinctOn: select.distinctOn\n          ? freeze([...select.distinctOn, ...expressions])\n          : freeze(expressions),\n      })\n    },\n\n    cloneWithFrontModifier(select, modifier) {\n      return freeze({\n        ...select,\n        frontModifiers: select.frontModifiers\n          ? freeze([...select.frontModifiers, modifier])\n          : freeze([modifier]),\n      })\n    },\n\n    // TODO: remove in v0.29\n    /**\n     * @deprecated Use `QueryNode.cloneWithoutOrderBy` instead.\n     */\n    cloneWithOrderByItems: (node, items) =>\n      QueryNode.cloneWithOrderByItems(node, items),\n\n    cloneWithGroupByItems(selectNode, items) {\n      return freeze({\n        ...selectNode,\n        groupBy: selectNode.groupBy\n          ? GroupByNode.cloneWithItems(selectNode.groupBy, items)\n          : GroupByNode.create(items),\n      })\n    },\n\n    cloneWithLimit(selectNode, limit) {\n      return freeze({\n        ...selectNode,\n        limit,\n      })\n    },\n\n    cloneWithOffset(selectNode, offset) {\n      return freeze({\n        ...selectNode,\n        offset,\n      })\n    },\n\n    cloneWithFetch(selectNode, fetch) {\n      return freeze({\n        ...selectNode,\n        fetch,\n      })\n    },\n\n    cloneWithHaving(selectNode, operation) {\n      return freeze({\n        ...selectNode,\n        having: selectNode.having\n          ? HavingNode.cloneWithOperation(selectNode.having, 'And', operation)\n          : HavingNode.create(operation),\n      })\n    },\n\n    cloneWithSetOperations(selectNode, setOperations) {\n      return freeze({\n        ...selectNode,\n        setOperations: selectNode.setOperations\n          ? freeze([...selectNode.setOperations, ...setOperations])\n          : freeze([...setOperations]),\n      })\n    },\n\n    cloneWithoutSelections(select) {\n      return freeze({\n        ...select,\n        selections: [],\n      })\n    },\n\n    cloneWithoutLimit(select) {\n      return freeze({\n        ...select,\n        limit: undefined,\n      })\n    },\n\n    cloneWithoutOffset(select) {\n      return freeze({\n        ...select,\n        offset: undefined,\n      })\n    },\n\n    // TODO: remove in v0.29\n    /**\n     * @deprecated Use `QueryNode.cloneWithoutOrderBy` instead.\n     */\n    cloneWithoutOrderBy: (node) => QueryNode.cloneWithoutOrderBy(node),\n\n    cloneWithoutGroupBy(select) {\n      return freeze({\n        ...select,\n        groupBy: undefined,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/selection-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { AliasNode } from './alias-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport { ReferenceNode } from './reference-node.js'\nimport { SelectAllNode } from './select-all-node.js'\nimport type { SimpleReferenceExpressionNode } from './simple-reference-expression-node.js'\nimport type { TableNode } from './table-node.js'\n\ntype SelectionNodeChild =\n  | SimpleReferenceExpressionNode\n  | AliasNode\n  | SelectAllNode\n\nexport interface SelectionNode extends OperationNode {\n  readonly kind: 'SelectionNode'\n  readonly selection: SelectionNodeChild\n}\n\ntype SelectionNodeFactory = Readonly<{\n  is(node: OperationNode): node is SelectionNode\n  create(selection: SelectionNodeChild): Readonly<SelectionNode>\n  createSelectAll(): Readonly<SelectionNode>\n  createSelectAllFromTable(table: TableNode): Readonly<SelectionNode>\n}>\n\n/**\n * @internal\n */\nexport const SelectionNode: SelectionNodeFactory = freeze<SelectionNodeFactory>(\n  {\n    is(node): node is SelectionNode {\n      return node.kind === 'SelectionNode'\n    },\n\n    create(selection) {\n      return freeze({\n        kind: 'SelectionNode',\n        selection: selection,\n      })\n    },\n\n    createSelectAll() {\n      return freeze({\n        kind: 'SelectionNode',\n        selection: SelectAllNode.create(),\n      })\n    },\n\n    createSelectAllFromTable(table) {\n      return freeze({\n        kind: 'SelectionNode',\n        selection: ReferenceNode.createSelectAll(table),\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/operation-node/set-operation-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport type SetOperator = 'union' | 'intersect' | 'except'\n\nexport interface SetOperationNode extends OperationNode {\n  kind: 'SetOperationNode'\n  operator: SetOperator\n  expression: OperationNode\n  all: boolean\n}\n\ntype SetOperationNodeFactory = Readonly<{\n  is(node: OperationNode): node is SetOperationNode\n  create(\n    operator: SetOperator,\n    expression: OperationNode,\n    all: boolean,\n  ): Readonly<SetOperationNode>\n}>\n\n/**\n * @internal\n */\nexport const SetOperationNode: SetOperationNodeFactory =\n  freeze<SetOperationNodeFactory>({\n    is(node): node is SetOperationNode {\n      return node.kind === 'SetOperationNode'\n    },\n\n    create(operator, expression, all) {\n      return freeze({\n        kind: 'SetOperationNode',\n        operator,\n        expression,\n        all,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/simple-reference-expression-node.ts",
    "content": "import type { ColumnNode } from './column-node.js'\nimport type { ReferenceNode } from './reference-node.js'\n\nexport type SimpleReferenceExpressionNode = ColumnNode | ReferenceNode\n"
  },
  {
    "path": "src/operation-node/table-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport { SchemableIdentifierNode } from './schemable-identifier-node.js'\n\nexport interface TableNode extends OperationNode {\n  readonly kind: 'TableNode'\n  readonly table: SchemableIdentifierNode\n}\n\ntype TableNodeFactory = Readonly<{\n  is(node: OperationNode): node is TableNode\n  create(table: string): Readonly<TableNode>\n  createWithSchema(schema: string, table: string): Readonly<TableNode>\n}>\n\n/**\n * @internal\n */\nexport const TableNode: TableNodeFactory = freeze<TableNodeFactory>({\n  is(node): node is TableNode {\n    return node.kind === 'TableNode'\n  },\n\n  create(table) {\n    return freeze({\n      kind: 'TableNode',\n      table: SchemableIdentifierNode.create(table),\n    })\n  },\n\n  createWithSchema(schema, table) {\n    return freeze({\n      kind: 'TableNode',\n      table: SchemableIdentifierNode.createWithSchema(schema, table),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/top-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport type TopModifier = 'percent' | 'with ties' | 'percent with ties'\n\nexport interface TopNode extends OperationNode {\n  readonly kind: 'TopNode'\n  readonly expression: number | bigint\n  readonly modifiers?: TopModifier\n}\n\ntype TopNodeFactory = Readonly<{\n  is(node: OperationNode): node is TopNode\n  create(\n    expression: number | bigint,\n    modifiers?: TopModifier,\n  ): Readonly<TopNode>\n}>\n\n/**\n * @internal\n */\nexport const TopNode: TopNodeFactory = freeze<TopNodeFactory>({\n  is(node): node is TopNode {\n    return node.kind === 'TopNode'\n  },\n\n  create(expression, modifiers?) {\n    return freeze({\n      kind: 'TopNode',\n      expression,\n      modifiers,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/tuple-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface TupleNode extends OperationNode {\n  readonly kind: 'TupleNode'\n  readonly values: ReadonlyArray<OperationNode>\n}\n\ntype TupleNodeFactory = Readonly<{\n  is(node: OperationNode): node is TupleNode\n  create(values: ReadonlyArray<OperationNode>): Readonly<TupleNode>\n}>\n\n/**\n * @internal\n */\nexport const TupleNode: TupleNodeFactory = freeze<TupleNodeFactory>({\n  is(node): node is TupleNode {\n    return node.kind === 'TupleNode'\n  },\n\n  create(values) {\n    return freeze({\n      kind: 'TupleNode',\n      values: freeze(values),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/unary-operation-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface UnaryOperationNode extends OperationNode {\n  readonly kind: 'UnaryOperationNode'\n  readonly operator: OperationNode\n  readonly operand: OperationNode\n}\n\ntype UnaryOperationNodeFactory = Readonly<{\n  is(node: OperationNode): node is UnaryOperationNode\n  create(\n    operator: OperationNode,\n    operand: OperationNode,\n  ): Readonly<UnaryOperationNode>\n}>\n\n/**\n * @internal\n */\nexport const UnaryOperationNode: UnaryOperationNodeFactory =\n  freeze<UnaryOperationNodeFactory>({\n    is(node): node is UnaryOperationNode {\n      return node.kind === 'UnaryOperationNode'\n    },\n\n    create(operator, operand) {\n      return freeze({\n        kind: 'UnaryOperationNode',\n        operator,\n        operand,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/unique-constraint-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { ColumnNode } from './column-node.js'\nimport { IdentifierNode } from './identifier-node.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface UniqueConstraintNode extends OperationNode {\n  readonly kind: 'UniqueConstraintNode'\n  readonly columns: ReadonlyArray<ColumnNode>\n  readonly name?: IdentifierNode\n  readonly nullsNotDistinct?: boolean\n  readonly deferrable?: boolean\n  readonly initiallyDeferred?: boolean\n}\n\nexport type UniqueConstraintNodeProps = Omit<\n  Partial<UniqueConstraintNode>,\n  'kind'\n>\n\ntype UniqueConstraintNodeFactory = Readonly<{\n  is(node: OperationNode): node is UniqueConstraintNode\n  create(\n    columns: string[],\n    constraintName?: string,\n    nullsNotDistinct?: boolean,\n  ): Readonly<UniqueConstraintNode>\n  cloneWith(\n    node: UniqueConstraintNode,\n    props: UniqueConstraintNodeProps,\n  ): Readonly<UniqueConstraintNode>\n}>\n\n/**\n * @internal\n */\nexport const UniqueConstraintNode: UniqueConstraintNodeFactory =\n  freeze<UniqueConstraintNodeFactory>({\n    is(node): node is UniqueConstraintNode {\n      return node.kind === 'UniqueConstraintNode'\n    },\n\n    create(columns, constraintName?, nullsNotDistinct?) {\n      return freeze({\n        kind: 'UniqueConstraintNode',\n        columns: freeze(columns.map(ColumnNode.create)),\n        name: constraintName\n          ? IdentifierNode.create(constraintName)\n          : undefined,\n        nullsNotDistinct,\n      })\n    },\n\n    cloneWith(node, props) {\n      return freeze({\n        ...node,\n        ...props,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/update-query-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { ColumnUpdateNode } from './column-update-node.js'\nimport type { JoinNode } from './join-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { ReturningNode } from './returning-node.js'\nimport type { WhereNode } from './where-node.js'\nimport type { WithNode } from './with-node.js'\nimport { FromNode } from './from-node.js'\nimport type { ExplainNode } from './explain-node.js'\nimport type { LimitNode } from './limit-node.js'\nimport type { TopNode } from './top-node.js'\nimport type { OutputNode } from './output-node.js'\nimport { ListNode } from './list-node.js'\nimport type { OrderByNode } from './order-by-node.js'\n\nexport interface UpdateQueryNode extends OperationNode {\n  readonly kind: 'UpdateQueryNode'\n  readonly table?: OperationNode\n  readonly from?: FromNode\n  readonly joins?: ReadonlyArray<JoinNode>\n  readonly where?: WhereNode\n  readonly updates?: ReadonlyArray<ColumnUpdateNode>\n  readonly returning?: ReturningNode\n  readonly with?: WithNode\n  readonly explain?: ExplainNode\n  readonly endModifiers?: ReadonlyArray<OperationNode>\n  readonly limit?: LimitNode\n  readonly top?: TopNode\n  readonly output?: OutputNode\n  readonly orderBy?: OrderByNode\n}\n\ntype UpdateQueryNodeFactory = Readonly<{\n  is(node: OperationNode): node is UpdateQueryNode\n  create(\n    tables: ReadonlyArray<OperationNode>,\n    withNode?: WithNode,\n  ): Readonly<UpdateQueryNode>\n  createWithoutTable(): Readonly<UpdateQueryNode>\n  cloneWithFromItems(\n    updateQuery: UpdateQueryNode,\n    fromItems: ReadonlyArray<OperationNode>,\n  ): Readonly<UpdateQueryNode>\n  cloneWithUpdates(\n    updateQuery: UpdateQueryNode,\n    updates: ReadonlyArray<ColumnUpdateNode>,\n  ): Readonly<UpdateQueryNode>\n  cloneWithLimit(\n    updateQuery: UpdateQueryNode,\n    limit: LimitNode,\n  ): Readonly<UpdateQueryNode>\n}>\n\n/**\n * @internal\n */\nexport const UpdateQueryNode: UpdateQueryNodeFactory =\n  freeze<UpdateQueryNodeFactory>({\n    is(node): node is UpdateQueryNode {\n      return node.kind === 'UpdateQueryNode'\n    },\n\n    create(tables, withNode?) {\n      return freeze({\n        kind: 'UpdateQueryNode',\n        // For backwards compatibility, use the raw table node when there's only one table\n        // and don't rename the property to something like `tables`.\n        table: tables.length === 1 ? tables[0] : ListNode.create(tables),\n        ...(withNode && { with: withNode }),\n      })\n    },\n\n    createWithoutTable() {\n      return freeze({\n        kind: 'UpdateQueryNode',\n      })\n    },\n\n    cloneWithFromItems(updateQuery, fromItems) {\n      return freeze({\n        ...updateQuery,\n        from: updateQuery.from\n          ? FromNode.cloneWithFroms(updateQuery.from, fromItems)\n          : FromNode.create(fromItems),\n      })\n    },\n\n    cloneWithUpdates(updateQuery, updates) {\n      return freeze({\n        ...updateQuery,\n        updates: updateQuery.updates\n          ? freeze([...updateQuery.updates, ...updates])\n          : updates,\n      })\n    },\n\n    cloneWithLimit(updateQuery, limit) {\n      return freeze({\n        ...updateQuery,\n        limit,\n      })\n    },\n  })\n"
  },
  {
    "path": "src/operation-node/using-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface UsingNode extends OperationNode {\n  readonly kind: 'UsingNode'\n  readonly tables: ReadonlyArray<OperationNode>\n}\n\ntype UsingNodeFactory = Readonly<{\n  is(node: OperationNode): node is UsingNode\n  create(tables: ReadonlyArray<OperationNode>): Readonly<UsingNode>\n  cloneWithTables(\n    using: UsingNode,\n    tables: ReadonlyArray<OperationNode>,\n  ): Readonly<UsingNode>\n}>\n\n/**\n * @internal\n */\nexport const UsingNode: UsingNodeFactory = freeze<UsingNodeFactory>({\n  is(node): node is UsingNode {\n    return node.kind === 'UsingNode'\n  },\n\n  create(tables) {\n    return freeze({\n      kind: 'UsingNode',\n      tables: freeze(tables),\n    })\n  },\n\n  cloneWithTables(using, tables) {\n    return freeze({\n      ...using,\n      tables: freeze([...using.tables, ...tables]),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/value-list-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface ValueListNode extends OperationNode {\n  readonly kind: 'ValueListNode'\n  readonly values: ReadonlyArray<OperationNode>\n}\n\ntype ValueListNodeFactory = Readonly<{\n  is(node: OperationNode): node is ValueListNode\n  create(values: ReadonlyArray<OperationNode>): Readonly<ValueListNode>\n}>\n\n/**\n * @internal\n */\nexport const ValueListNode: ValueListNodeFactory = freeze<ValueListNodeFactory>(\n  {\n    is(node): node is ValueListNode {\n      return node.kind === 'ValueListNode'\n    },\n\n    create(values) {\n      return freeze({\n        kind: 'ValueListNode',\n        values: freeze(values),\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/operation-node/value-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface ValueNode extends OperationNode {\n  readonly kind: 'ValueNode'\n  readonly value: unknown\n  readonly immediate?: boolean\n}\n\ntype ValueNodeFactory = Readonly<{\n  is(node: OperationNode): node is ValueNode\n  create(value: unknown): Readonly<ValueNode>\n  createImmediate(value: unknown): Readonly<ValueNode>\n}>\n\n/**\n * @internal\n */\nexport const ValueNode: ValueNodeFactory = freeze<ValueNodeFactory>({\n  is(node): node is ValueNode {\n    return node.kind === 'ValueNode'\n  },\n\n  create(value) {\n    return freeze({\n      kind: 'ValueNode',\n      value,\n    })\n  },\n\n  createImmediate(value) {\n    return freeze({\n      kind: 'ValueNode',\n      value,\n      immediate: true,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/values-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { PrimitiveValueListNode } from './primitive-value-list-node.js'\nimport type { ValueListNode } from './value-list-node.js'\n\nexport type ValuesItemNode = ValueListNode | PrimitiveValueListNode\n\nexport interface ValuesNode extends OperationNode {\n  readonly kind: 'ValuesNode'\n  readonly values: ReadonlyArray<ValuesItemNode>\n}\n\ntype ValuesNodeFactory = Readonly<{\n  is(node: OperationNode): node is ValuesNode\n  create(values: ReadonlyArray<ValuesItemNode>): Readonly<ValuesNode>\n}>\n\n/**\n * @internal\n */\nexport const ValuesNode: ValuesNodeFactory = freeze<ValuesNodeFactory>({\n  is(node): node is ValuesNode {\n    return node.kind === 'ValuesNode'\n  },\n\n  create(values) {\n    return freeze({\n      kind: 'ValuesNode',\n      values: freeze(values),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/when-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\n\nexport interface WhenNode extends OperationNode {\n  readonly kind: 'WhenNode'\n  readonly condition: OperationNode\n  readonly result?: OperationNode\n}\n\ntype WhenNodeFactory = Readonly<{\n  is(node: OperationNode): node is WhenNode\n  create(condition: OperationNode): Readonly<WhenNode>\n  cloneWithResult(whenNode: WhenNode, result: OperationNode): Readonly<WhenNode>\n}>\n\n/**\n * @internal\n */\nexport const WhenNode: WhenNodeFactory = freeze<WhenNodeFactory>({\n  is(node): node is WhenNode {\n    return node.kind === 'WhenNode'\n  },\n\n  create(condition) {\n    return freeze({\n      kind: 'WhenNode',\n      condition,\n    })\n  },\n\n  cloneWithResult(whenNode, result) {\n    return freeze({\n      ...whenNode,\n      result,\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/where-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { AndNode } from './and-node.js'\nimport type { OperationNode } from './operation-node.js'\nimport { OrNode } from './or-node.js'\n\nexport interface WhereNode extends OperationNode {\n  readonly kind: 'WhereNode'\n  readonly where: OperationNode\n}\n\ntype WhereNodeFactory = Readonly<{\n  is(node: OperationNode): node is WhereNode\n  create(filter: OperationNode): Readonly<WhereNode>\n  cloneWithOperation(\n    whereNode: WhereNode,\n    operator: 'And' | 'Or',\n    operation: OperationNode,\n  ): Readonly<WhereNode>\n}>\n\n/**\n * @internal\n */\nexport const WhereNode: WhereNodeFactory = freeze<WhereNodeFactory>({\n  is(node): node is WhereNode {\n    return node.kind === 'WhereNode'\n  },\n\n  create(filter) {\n    return freeze({\n      kind: 'WhereNode',\n      where: filter,\n    })\n  },\n\n  cloneWithOperation(whereNode, operator, operation) {\n    return freeze({\n      ...whereNode,\n      where:\n        operator === 'And'\n          ? AndNode.create(whereNode.where, operation)\n          : OrNode.create(whereNode.where, operation),\n    })\n  },\n})\n"
  },
  {
    "path": "src/operation-node/with-node.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport type { OperationNode } from './operation-node.js'\nimport type { CommonTableExpressionNode } from './common-table-expression-node.js'\n\nexport type WithNodeParams = Omit<WithNode, 'kind' | 'expressions'>\n\nexport interface WithNode extends OperationNode {\n  readonly kind: 'WithNode'\n  readonly expressions: ReadonlyArray<CommonTableExpressionNode>\n  readonly recursive?: boolean\n}\n\ntype WithNodeFactory = Readonly<{\n  is(node: OperationNode): node is WithNode\n  create(\n    expression: CommonTableExpressionNode,\n    params?: WithNodeParams,\n  ): Readonly<WithNode>\n  cloneWithExpression(\n    withNode: WithNode,\n    expression: CommonTableExpressionNode,\n  ): Readonly<WithNode>\n}>\n\n/**\n * @internal\n */\nexport const WithNode: WithNodeFactory = freeze<WithNodeFactory>({\n  is(node): node is WithNode {\n    return node.kind === 'WithNode'\n  },\n\n  create(expression, params?) {\n    return freeze({\n      kind: 'WithNode',\n      expressions: freeze([expression]),\n      ...params,\n    })\n  },\n\n  cloneWithExpression(withNode, expression) {\n    return freeze({\n      ...withNode,\n      expressions: freeze([...withNode.expressions, expression]),\n    })\n  },\n})\n"
  },
  {
    "path": "src/parser/binary-operation-parser.ts",
    "content": "import { BinaryOperationNode } from '../operation-node/binary-operation-node.js'\nimport {\n  isBoolean,\n  isNull,\n  isString,\n  isUndefined,\n} from '../util/object-utils.js'\nimport {\n  type OperationNodeSource,\n  isOperationNodeSource,\n} from '../operation-node/operation-node-source.js'\nimport {\n  OperatorNode,\n  type ComparisonOperator,\n  type BinaryOperator,\n  type Operator,\n  OPERATORS,\n} from '../operation-node/operator-node.js'\nimport {\n  type ExtractTypeFromReferenceExpression,\n  type ExtractTypeFromStringReference,\n  parseReferenceExpression,\n  type ReferenceExpression,\n  type StringReference,\n} from './reference-parser.js'\nimport {\n  parseValueExpression,\n  parseValueExpressionOrList,\n  type ValueExpression,\n  type ValueExpressionOrList,\n} from './value-parser.js'\nimport { ValueNode } from '../operation-node/value-node.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport type { Expression } from '../expression/expression.js'\nimport type { SelectType } from '../util/column-type.js'\nimport { AndNode } from '../operation-node/and-node.js'\nimport { ParensNode } from '../operation-node/parens-node.js'\nimport { OrNode } from '../operation-node/or-node.js'\nimport type { WhenNode } from '../operation-node/when-node.js'\nimport type { RawNode } from '../operation-node/raw-node.js'\n\nexport type OperandValueExpression<\n  DB,\n  TB extends keyof DB,\n  RE,\n> = ValueExpression<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>\n\nexport type OperandValueExpressionOrList<\n  DB,\n  TB extends keyof DB,\n  RE,\n> = ValueExpressionOrList<\n  DB,\n  TB,\n  ExtractTypeFromReferenceExpression<DB, TB, RE> | null\n>\n\nexport type OperatorExpression = Operator | Expression<unknown>\nexport type BinaryOperatorExpression = BinaryOperator | Expression<unknown>\n\nexport type ComparisonOperatorExpression =\n  | ComparisonOperator\n  | Expression<unknown>\n\nexport type FilterObject<DB, TB extends keyof DB> = {\n  [R in StringReference<DB, TB>]?: ValueExpressionOrList<\n    DB,\n    TB,\n    SelectType<ExtractTypeFromStringReference<DB, TB, R>>\n  >\n}\n\nexport function parseValueBinaryOperationOrExpression(\n  args: any[],\n): OperationNode {\n  if (args.length === 3) {\n    return parseValueBinaryOperation(args[0], args[1], args[2])\n  } else if (args.length === 1) {\n    return parseValueExpression(args[0])\n  }\n\n  throw new Error(`invalid arguments: ${JSON.stringify(args)}`)\n}\n\nexport function parseValueBinaryOperation(\n  left: ReferenceExpression<any, any>,\n  operator: BinaryOperatorExpression,\n  right: OperandValueExpressionOrList<any, any, any>,\n): BinaryOperationNode {\n  if (isIsOperator(operator) && needsIsOperator(right)) {\n    return BinaryOperationNode.create(\n      parseReferenceExpression(left),\n      parseOperator(operator),\n      ValueNode.createImmediate(right),\n    )\n  }\n\n  return BinaryOperationNode.create(\n    parseReferenceExpression(left),\n    parseOperator(operator),\n    parseValueExpressionOrList(right),\n  )\n}\n\nexport function parseReferentialBinaryOperation(\n  left: ReferenceExpression<any, any>,\n  operator: BinaryOperatorExpression,\n  right: OperandValueExpressionOrList<any, any, any>,\n): BinaryOperationNode {\n  return BinaryOperationNode.create(\n    parseReferenceExpression(left),\n    parseOperator(operator),\n    parseReferenceExpression(right),\n  )\n}\n\nexport function parseFilterObject(\n  obj: Readonly<FilterObject<any, any>>,\n  combinator: 'and' | 'or',\n): OperationNode {\n  return parseFilterList(\n    Object.entries(obj)\n      .filter(([, v]) => !isUndefined(v))\n      .map(([k, v]) =>\n        parseValueBinaryOperation(k, needsIsOperator(v) ? 'is' : '=', v),\n      ),\n    combinator,\n  )\n}\n\nexport function parseFilterList(\n  list: ReadonlyArray<OperationNodeSource | OperationNode>,\n  combinator: 'and' | 'or',\n  withParens = true,\n): OperationNode {\n  const combine = combinator === 'and' ? AndNode.create : OrNode.create\n\n  if (list.length === 0) {\n    return BinaryOperationNode.create(\n      ValueNode.createImmediate(1),\n      OperatorNode.create('='),\n      ValueNode.createImmediate(combinator === 'and' ? 1 : 0),\n    )\n  }\n\n  let node = toOperationNode(list[0])\n\n  for (let i = 1; i < list.length; ++i) {\n    node = combine(node, toOperationNode(list[i]))\n  }\n\n  if (list.length > 1 && withParens) {\n    return ParensNode.create(node)\n  }\n\n  return node\n}\n\nfunction isIsOperator(\n  operator: BinaryOperatorExpression,\n): operator is 'is' | 'is not' {\n  return operator === 'is' || operator === 'is not'\n}\n\nfunction needsIsOperator(value: unknown): value is null | boolean {\n  return isNull(value) || isBoolean(value)\n}\n\nfunction parseOperator(operator: OperatorExpression): OperationNode {\n  if (isString(operator) && OPERATORS.includes(operator)) {\n    return OperatorNode.create(operator)\n  }\n\n  if (isOperationNodeSource(operator)) {\n    return operator.toOperationNode()\n  }\n\n  throw new Error(`invalid operator ${JSON.stringify(operator)}`)\n}\n\nfunction toOperationNode(\n  nodeOrSource: OperationNode | OperationNodeSource,\n): OperationNode {\n  return isOperationNodeSource(nodeOrSource)\n    ? nodeOrSource.toOperationNode()\n    : nodeOrSource\n}\n"
  },
  {
    "path": "src/parser/coalesce-parser.ts",
    "content": "import type { ExtractTypeFromReferenceExpression } from './reference-parser.js'\n\nexport type ExtractTypeFromCoalesce1<\n  DB,\n  TB extends keyof DB,\n  R1,\n> = ExtractTypeFromReferenceExpression<DB, TB, R1>\n\nexport type ExtractTypeFromCoalesce2<\n  DB,\n  TB extends keyof DB,\n  R1,\n  R2,\n> = ExtractTypeFromCoalesceValues2<\n  ExtractTypeFromReferenceExpression<DB, TB, R1>,\n  ExtractTypeFromReferenceExpression<DB, TB, R2>\n>\n\ntype ExtractTypeFromCoalesceValues2<V1, V2> = null extends V1\n  ? null extends V2\n    ? V1 | V2\n    : NotNull<V1 | V2>\n  : NotNull<V1>\n\nexport type ExtractTypeFromCoalesce3<\n  DB,\n  TB extends keyof DB,\n  R1,\n  R2,\n  R3,\n> = ExtractTypeFromCoalesceValues3<\n  ExtractTypeFromReferenceExpression<DB, TB, R1>,\n  ExtractTypeFromReferenceExpression<DB, TB, R2>,\n  ExtractTypeFromReferenceExpression<DB, TB, R3>\n>\n\ntype ExtractTypeFromCoalesceValues3<V1, V2, V3> = null extends V1\n  ? null extends V2\n    ? null extends V3\n      ? V1 | V2 | V3\n      : NotNull<V1 | V2 | V3>\n    : NotNull<V1 | V2>\n  : NotNull<V1>\n\nexport type ExtractTypeFromCoalesce4<\n  DB,\n  TB extends keyof DB,\n  R1,\n  R2,\n  R3,\n  R4,\n> = ExtractTypeFromCoalesceValues4<\n  ExtractTypeFromReferenceExpression<DB, TB, R1>,\n  ExtractTypeFromReferenceExpression<DB, TB, R2>,\n  ExtractTypeFromReferenceExpression<DB, TB, R3>,\n  ExtractTypeFromReferenceExpression<DB, TB, R4>\n>\n\ntype ExtractTypeFromCoalesceValues4<V1, V2, V3, V4> = null extends V1\n  ? null extends V2\n    ? null extends V3\n      ? null extends V4\n        ? V1 | V2 | V3 | V4\n        : NotNull<V1 | V2 | V3 | V4>\n      : NotNull<V1 | V2 | V3>\n    : NotNull<V1 | V2>\n  : NotNull<V1>\n\nexport type ExtractTypeFromCoalesce5<\n  DB,\n  TB extends keyof DB,\n  R1,\n  R2,\n  R3,\n  R4,\n  R5,\n> = ExtractTypeFromCoalesceValues5<\n  ExtractTypeFromReferenceExpression<DB, TB, R1>,\n  ExtractTypeFromReferenceExpression<DB, TB, R2>,\n  ExtractTypeFromReferenceExpression<DB, TB, R3>,\n  ExtractTypeFromReferenceExpression<DB, TB, R4>,\n  ExtractTypeFromReferenceExpression<DB, TB, R5>\n>\n\ntype ExtractTypeFromCoalesceValues5<V1, V2, V3, V4, V5> = null extends V1\n  ? null extends V2\n    ? null extends V3\n      ? null extends V4\n        ? null extends V5\n          ? V1 | V2 | V3 | V4 | V5\n          : NotNull<V1 | V2 | V3 | V4 | V5>\n        : NotNull<V1 | V2 | V3 | V4>\n      : NotNull<V1 | V2 | V3>\n    : NotNull<V1 | V2>\n  : NotNull<V1>\n\ntype NotNull<T> = Exclude<T, null>\n"
  },
  {
    "path": "src/parser/collate-parser.ts",
    "content": "export type Collation =\n  // anything super common or simple should be added here.\n  // https://sqlite.org/datatype3.html#collating_sequences\n  | 'nocase'\n  | 'binary'\n  | 'rtrim'\n  // otherwise, allow any string, while still providing autocompletion.\n  | (string & {})\n"
  },
  {
    "path": "src/parser/data-type-parser.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport {\n  type ColumnDataType,\n  DataTypeNode,\n  isColumnDataType,\n} from '../operation-node/data-type-node.js'\nimport { isOperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\n\nexport type DataTypeExpression = ColumnDataType | Expression<any>\n\nexport function parseDataTypeExpression(\n  dataType: DataTypeExpression,\n): OperationNode {\n  if (isOperationNodeSource(dataType)) {\n    return dataType.toOperationNode()\n  }\n\n  if (isColumnDataType(dataType)) {\n    return DataTypeNode.create(dataType)\n  }\n\n  throw new Error(`invalid column data type ${JSON.stringify(dataType)}`)\n}\n"
  },
  {
    "path": "src/parser/default-value-parser.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport { isOperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport { ValueNode } from '../operation-node/value-node.js'\n\nexport type DefaultValueExpression = unknown | Expression<unknown>\n\nexport function parseDefaultValueExpression(\n  value: DefaultValueExpression,\n): OperationNode {\n  return isOperationNodeSource(value)\n    ? value.toOperationNode()\n    : ValueNode.createImmediate(value)\n}\n"
  },
  {
    "path": "src/parser/delete-from-parser.ts",
    "content": "import type { DeleteQueryBuilder } from '../query-builder/delete-query-builder.js'\nimport type { DeleteResult } from '../query-builder/delete-result.js'\nimport type { ShallowRecord } from '../util/type-utils.js'\nimport type {\n  ExtractTableAlias,\n  From,\n  FromTables,\n  TableExpressionOrList,\n} from './table-parser.js'\n\nexport type DeleteFrom<DB, TE extends TableExpressionOrList<DB, never>> = [\n  TE,\n] extends [keyof DB]\n  ? // This branch creates a good-looking type for the most common case:\n    // deleteFrom('person') --> DeleteQueryBuilder<DB, 'person', {}>.\n    // ExtractTableAlias is needed for the case where DB == any. Without it:\n    // deleteFrom('person as p') --> DeleteQueryBuilder<DB, 'person as p', {}>\n    DeleteQueryBuilder<DB, ExtractTableAlias<DB, TE>, DeleteResult>\n  : // This branch creates a good-looking type for common aliased case:\n    // deleteFrom('person as p') --> DeleteQueryBuilder<DB & { p: Person }, 'p', {}>.\n    [TE] extends [`${infer T} as ${infer A}`]\n    ? T extends keyof DB\n      ? DeleteQueryBuilder<DB & ShallowRecord<A, DB[T]>, A, DeleteResult>\n      : never\n    : TE extends ReadonlyArray<infer T>\n      ? DeleteQueryBuilder<From<DB, T>, FromTables<DB, never, T>, DeleteResult>\n      : DeleteQueryBuilder<\n          From<DB, TE>,\n          FromTables<DB, never, TE>,\n          DeleteResult\n        >\n"
  },
  {
    "path": "src/parser/expression-parser.ts",
    "content": "import {\n  type AliasedExpression,\n  type Expression,\n  isAliasedExpression,\n  isExpression,\n} from '../expression/expression.js'\nimport type { AliasNode } from '../operation-node/alias-node.js'\nimport { isOperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport {\n  expressionBuilder,\n  type ExpressionBuilder,\n} from '../expression/expression-builder.js'\nimport type { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js'\nimport { isFunction } from '../util/object-utils.js'\n\n/**\n * Like `Expression<V>` but also accepts a select query with an output\n * type extending `Record<string, V>`. This type is useful because SQL\n * treats records with a single column as single values.\n */\nexport type OperandExpression<V> =\n  // SQL treats a subquery with a single selection as a scalar. That's\n  // why we need to explicitly allow `SelectQueryBuilder` here with a\n  // `Record<string, V>` output type, even though `SelectQueryBuilder`\n  // is also an `Expression`.\n  Expression<V> | SelectQueryBuilderExpression<Record<string, V>>\n\nexport type ExpressionOrFactory<DB, TB extends keyof DB, V> =\n  | OperandExpression<V>\n  | OperandExpressionFactory<DB, TB, V>\n\nexport type AliasedExpressionOrFactory<DB, TB extends keyof DB> =\n  | AliasedExpression<any, any>\n  | AliasedExpressionFactory<DB, TB>\n\nexport type ExpressionFactory<DB, TB extends keyof DB, V> = (\n  eb: ExpressionBuilder<DB, TB>,\n) => Expression<V>\n\ntype OperandExpressionFactory<DB, TB extends keyof DB, V> = (\n  eb: ExpressionBuilder<DB, TB>,\n) => OperandExpression<V>\n\ntype AliasedExpressionFactory<DB, TB extends keyof DB> = (\n  eb: ExpressionBuilder<DB, TB>,\n) => AliasedExpression<any, any>\n\nexport function parseExpression(\n  exp: ExpressionOrFactory<any, any, any>,\n): OperationNode {\n  if (isOperationNodeSource(exp)) {\n    return exp.toOperationNode()\n  } else if (isFunction(exp)) {\n    return exp(expressionBuilder()).toOperationNode()\n  }\n\n  throw new Error(`invalid expression: ${JSON.stringify(exp)}`)\n}\n\nexport function parseAliasedExpression(\n  exp: AliasedExpressionOrFactory<any, any>,\n): AliasNode {\n  if (isOperationNodeSource(exp)) {\n    return exp.toOperationNode()\n  } else if (isFunction(exp)) {\n    return exp(expressionBuilder()).toOperationNode()\n  }\n\n  throw new Error(`invalid aliased expression: ${JSON.stringify(exp)}`)\n}\n\nexport function isExpressionOrFactory(\n  obj: unknown,\n): obj is ExpressionOrFactory<any, any, any> {\n  return isExpression(obj) || isAliasedExpression(obj) || isFunction(obj)\n}\n"
  },
  {
    "path": "src/parser/fetch-parser.ts",
    "content": "import { type FetchModifier, FetchNode } from '../operation-node/fetch-node.js'\nimport { isBigInt, isNumber } from '../util/object-utils.js'\n\nexport function parseFetch(\n  rowCount: number | bigint,\n  modifier: FetchModifier,\n): FetchNode {\n  if (!isNumber(rowCount) && !isBigInt(rowCount)) {\n    throw new Error(`Invalid fetch row count: ${rowCount}`)\n  }\n\n  if (!isFetchModifier(modifier)) {\n    throw new Error(`Invalid fetch modifier: ${modifier}`)\n  }\n\n  return FetchNode.create(rowCount, modifier)\n}\n\nfunction isFetchModifier(value: any): value is FetchModifier {\n  return value === 'only' || value === 'with ties'\n}\n"
  },
  {
    "path": "src/parser/group-by-parser.ts",
    "content": "import { GroupByItemNode } from '../operation-node/group-by-item-node.js'\nimport {\n  expressionBuilder,\n  type ExpressionBuilder,\n} from '../expression/expression-builder.js'\nimport { isFunction } from '../util/object-utils.js'\nimport {\n  parseReferenceExpressionOrList,\n  type ReferenceExpression,\n} from './reference-parser.js'\n\nexport type GroupByExpression<DB, TB extends keyof DB, O> =\n  | ReferenceExpression<DB, TB>\n  | (keyof O & string)\n\nexport type GroupByArg<DB, TB extends keyof DB, O> =\n  | GroupByExpression<DB, TB, O>\n  | ReadonlyArray<GroupByExpression<DB, TB, O>>\n  | ((\n      eb: ExpressionBuilder<DB, TB>,\n    ) => ReadonlyArray<GroupByExpression<DB, TB, O>>)\n\nexport function parseGroupBy(\n  groupBy: GroupByArg<any, any, any>,\n): GroupByItemNode[] {\n  groupBy = isFunction(groupBy) ? groupBy(expressionBuilder()) : groupBy\n  return parseReferenceExpressionOrList(groupBy).map(GroupByItemNode.create)\n}\n"
  },
  {
    "path": "src/parser/identifier-parser.ts",
    "content": "import { SchemableIdentifierNode } from '../operation-node/schemable-identifier-node.js'\n\nexport function parseSchemableIdentifier(id: string): SchemableIdentifierNode {\n  const SCHEMA_SEPARATOR = '.'\n\n  if (id.includes(SCHEMA_SEPARATOR)) {\n    const parts = id.split(SCHEMA_SEPARATOR).map(trim)\n\n    if (parts.length === 2) {\n      return SchemableIdentifierNode.createWithSchema(parts[0], parts[1])\n    } else {\n      throw new Error(`invalid schemable identifier ${id}`)\n    }\n  } else {\n    return SchemableIdentifierNode.create(id)\n  }\n}\n\nfunction trim(str: string): string {\n  return str.trim()\n}\n"
  },
  {
    "path": "src/parser/insert-values-parser.ts",
    "content": "import { ColumnNode } from '../operation-node/column-node.js'\nimport { PrimitiveValueListNode } from '../operation-node/primitive-value-list-node.js'\nimport { ValueListNode } from '../operation-node/value-list-node.js'\nimport {\n  freeze,\n  isFunction,\n  isReadonlyArray,\n  isUndefined,\n} from '../util/object-utils.js'\nimport { parseValueExpression, type ValueExpression } from './value-parser.js'\nimport { ValuesNode } from '../operation-node/values-node.js'\nimport type {\n  NonNullableInsertKeys,\n  NullableInsertKeys,\n  InsertType,\n} from '../util/column-type.js'\nimport { isExpressionOrFactory } from './expression-parser.js'\nimport { DefaultInsertValueNode } from '../operation-node/default-insert-value-node.js'\nimport {\n  expressionBuilder,\n  type ExpressionBuilder,\n} from '../expression/expression-builder.js'\n\nexport type InsertObject<DB, TB extends keyof DB> = {\n  [C in NonNullableInsertKeys<DB[TB]>]: ValueExpression<\n    DB,\n    TB,\n    InsertType<DB[TB][C]>\n  >\n} & {\n  [C in NullableInsertKeys<DB[TB]>]?:\n    | ValueExpression<DB, TB, InsertType<DB[TB][C]>>\n    | undefined\n}\n\nexport type InsertObjectOrList<DB, TB extends keyof DB> =\n  | InsertObject<DB, TB>\n  | ReadonlyArray<InsertObject<DB, TB>>\n\nexport type InsertObjectOrListFactory<\n  DB,\n  TB extends keyof DB,\n  UT extends keyof DB = never,\n> = (eb: ExpressionBuilder<DB, TB | UT>) => InsertObjectOrList<DB, TB>\n\nexport type InsertExpression<\n  DB,\n  TB extends keyof DB,\n  UT extends keyof DB = never,\n> = InsertObjectOrList<DB, TB> | InsertObjectOrListFactory<DB, TB, UT>\n\nexport function parseInsertExpression(\n  arg: InsertExpression<any, any, any>,\n): [ReadonlyArray<ColumnNode>, ValuesNode] {\n  const objectOrList = isFunction(arg) ? arg(expressionBuilder()) : arg\n  const list = isReadonlyArray(objectOrList)\n    ? objectOrList\n    : freeze([objectOrList])\n\n  return parseInsertColumnsAndValues(list)\n}\n\nfunction parseInsertColumnsAndValues(\n  rows: ReadonlyArray<InsertObject<any, any>>,\n): [ReadonlyArray<ColumnNode>, ValuesNode] {\n  const columns = parseColumnNamesAndIndexes(rows)\n\n  return [\n    freeze([...columns.keys()].map(ColumnNode.create)),\n    ValuesNode.create(rows.map((row) => parseRowValues(row, columns))),\n  ]\n}\n\nfunction parseColumnNamesAndIndexes(\n  rows: ReadonlyArray<InsertObject<any, any>>,\n): Map<string, number> {\n  const columns = new Map<string, number>()\n\n  for (const row of rows) {\n    const cols = Object.keys(row)\n\n    for (const col of cols) {\n      if (!columns.has(col) && row[col] !== undefined) {\n        columns.set(col, columns.size)\n      }\n    }\n  }\n\n  return columns\n}\n\nfunction parseRowValues(\n  row: InsertObject<any, any>,\n  columns: Map<string, number>,\n): PrimitiveValueListNode | ValueListNode {\n  const rowColumns = Object.keys(row)\n\n  const rowValues = Array.from({\n    length: columns.size,\n  })\n\n  let hasUndefinedOrComplexColumns = false\n  let indexedRowColumns = rowColumns.length\n\n  for (const col of rowColumns) {\n    const columnIdx = columns.get(col)\n\n    if (isUndefined(columnIdx)) {\n      indexedRowColumns--\n      continue\n    }\n\n    const value = row[col]\n\n    if (isUndefined(value) || isExpressionOrFactory(value)) {\n      hasUndefinedOrComplexColumns = true\n    }\n\n    rowValues[columnIdx] = value\n  }\n\n  const hasMissingColumns = indexedRowColumns < columns.size\n\n  if (hasMissingColumns || hasUndefinedOrComplexColumns) {\n    const defaultValue = DefaultInsertValueNode.create()\n\n    return ValueListNode.create(\n      rowValues.map((it) =>\n        isUndefined(it) ? defaultValue : parseValueExpression(it),\n      ),\n    )\n  }\n\n  return PrimitiveValueListNode.create(rowValues)\n}\n"
  },
  {
    "path": "src/parser/join-parser.ts",
    "content": "import { JoinNode, type JoinType } from '../operation-node/join-node.js'\nimport type { JoinBuilder } from '../query-builder/join-builder.js'\nimport type {\n  AnyColumn,\n  AnyColumnWithTable,\n  DrainOuterGeneric,\n} from '../util/type-utils.js'\nimport { parseReferentialBinaryOperation } from './binary-operation-parser.js'\nimport { createJoinBuilder } from './parse-utils.js'\nimport {\n  type From,\n  type FromTables,\n  type TableExpression,\n  parseTableExpression,\n} from './table-parser.js'\n\nexport type JoinReferenceExpression<\n  DB,\n  TB extends keyof DB,\n  TE,\n> = DrainOuterGeneric<\n  AnyJoinColumn<DB, TB, TE> | AnyJoinColumnWithTable<DB, TB, TE>\n>\n\nexport type JoinCallbackExpression<DB, TB extends keyof DB, TE> = (\n  join: JoinBuilder<From<DB, TE>, FromTables<DB, TB, TE>>,\n) => JoinBuilder<any, any>\n\ntype AnyJoinColumn<DB, TB extends keyof DB, TE> = AnyColumn<\n  From<DB, TE>,\n  FromTables<DB, TB, TE>\n>\n\ntype AnyJoinColumnWithTable<DB, TB extends keyof DB, TE> = AnyColumnWithTable<\n  From<DB, TE>,\n  FromTables<DB, TB, TE>\n>\n\nexport function parseJoin(joinType: JoinType, args: any[]): JoinNode {\n  if (args.length === 3) {\n    return parseSingleOnJoin(joinType, args[0], args[1], args[2])\n  } else if (args.length === 2) {\n    return parseCallbackJoin(joinType, args[0], args[1])\n  } else if (args.length === 1) {\n    return parseOnlessJoin(joinType, args[0])\n  } else {\n    throw new Error('not implemented')\n  }\n}\n\nfunction parseCallbackJoin(\n  joinType: JoinType,\n  from: TableExpression<any, any>,\n  callback: JoinCallbackExpression<any, any, any>,\n): JoinNode {\n  return callback(createJoinBuilder(joinType, from)).toOperationNode()\n}\n\nfunction parseSingleOnJoin(\n  joinType: JoinType,\n  from: TableExpression<any, any>,\n  lhsColumn: string,\n  rhsColumn: string,\n): JoinNode {\n  return JoinNode.createWithOn(\n    joinType,\n    parseTableExpression(from),\n    parseReferentialBinaryOperation(lhsColumn, '=', rhsColumn),\n  )\n}\n\nfunction parseOnlessJoin(\n  joinType: JoinType,\n  from: TableExpression<any, any>,\n): JoinNode {\n  return JoinNode.create(joinType, parseTableExpression(from))\n}\n"
  },
  {
    "path": "src/parser/merge-into-parser.ts",
    "content": "import type { MergeQueryBuilder } from '../query-builder/merge-query-builder.js'\nimport type { MergeResult } from '../query-builder/merge-result.js'\nimport type { ShallowRecord } from '../util/type-utils.js'\nimport type { ExtractTableAlias, SimpleTableReference } from './table-parser.js'\n\nexport type MergeInto<DB, TE extends SimpleTableReference<DB>> = [TE] extends [\n  keyof DB,\n]\n  ? MergeQueryBuilder<DB, ExtractTableAlias<DB, TE>, MergeResult>\n  : [TE] extends [`${infer T} as ${infer A}`]\n    ? T extends keyof DB\n      ? MergeQueryBuilder<DB & ShallowRecord<A, DB[T]>, A, MergeResult>\n      : never\n    : never\n"
  },
  {
    "path": "src/parser/merge-parser.ts",
    "content": "import type { InsertQueryNode } from '../operation-node/insert-query-node.js'\nimport { MatchedNode } from '../operation-node/matched-node.js'\nimport {\n  type OperationNodeSource,\n  isOperationNodeSource,\n} from '../operation-node/operation-node-source.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport { RawNode } from '../operation-node/raw-node.js'\nimport { WhenNode } from '../operation-node/when-node.js'\nimport { isString } from '../util/object-utils.js'\nimport {\n  parseFilterList,\n  parseReferentialBinaryOperation,\n  parseValueBinaryOperationOrExpression,\n} from './binary-operation-parser.js'\n\nexport function parseMergeWhen(\n  type: {\n    isMatched: boolean\n    bySource?: boolean\n  },\n  args?: any[],\n  refRight?: boolean,\n): WhenNode {\n  return WhenNode.create(\n    parseFilterList(\n      [\n        MatchedNode.create(!type.isMatched, type.bySource),\n        ...(args && args.length > 0\n          ? [\n              args.length === 3 && refRight\n                ? parseReferentialBinaryOperation(args[0], args[1], args[2])\n                : parseValueBinaryOperationOrExpression(args),\n            ]\n          : []),\n      ],\n      'and',\n      false,\n    ),\n  )\n}\n\nexport function parseMergeThen(\n  result: 'delete' | 'do nothing' | OperationNodeSource | InsertQueryNode,\n): OperationNode {\n  if (isString(result)) {\n    return RawNode.create([result], [])\n  }\n\n  if (isOperationNodeSource(result)) {\n    return result.toOperationNode()\n  }\n\n  return result\n}\n"
  },
  {
    "path": "src/parser/on-commit-action-parse.ts",
    "content": "import {\n  type OnCommitAction,\n  ON_COMMIT_ACTIONS,\n} from '../operation-node/create-table-node.js'\n\nexport function parseOnCommitAction(action: OnCommitAction): OnCommitAction {\n  if (ON_COMMIT_ACTIONS.includes(action)) {\n    return action\n  }\n\n  throw new Error(`invalid OnCommitAction ${action}`)\n}\n"
  },
  {
    "path": "src/parser/on-modify-action-parser.ts",
    "content": "import {\n  type OnModifyForeignAction,\n  ON_MODIFY_FOREIGN_ACTIONS,\n} from '../operation-node/references-node.js'\n\nexport function parseOnModifyForeignAction(\n  action: OnModifyForeignAction,\n): OnModifyForeignAction {\n  if (ON_MODIFY_FOREIGN_ACTIONS.includes(action)) {\n    return action\n  }\n\n  throw new Error(`invalid OnModifyForeignAction ${action}`)\n}\n"
  },
  {
    "path": "src/parser/order-by-parser.ts",
    "content": "import {\n  type DynamicReferenceBuilder,\n  isDynamicReferenceBuilder,\n} from '../dynamic/dynamic-reference-builder.js'\nimport { type Expression, isExpression } from '../expression/expression.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport { OrderByItemNode } from '../operation-node/order-by-item-node.js'\nimport { RawNode } from '../operation-node/raw-node.js'\nimport { OrderByItemBuilder } from '../query-builder/order-by-item-builder.js'\nimport { logOnce } from '../util/log-once.js'\nimport {\n  type ExpressionOrFactory,\n  isExpressionOrFactory,\n  parseExpression,\n} from './expression-parser.js'\nimport {\n  type ReferenceExpression,\n  type StringReference,\n  parseStringReference,\n} from './reference-parser.js'\n\nexport type OrderByExpression<DB, TB extends keyof DB, O> =\n  | StringReference<DB, TB>\n  | (keyof O & string)\n  | ExpressionOrFactory<DB, TB, any>\n  | DynamicReferenceBuilder<any>\n\nexport type OrderByModifiers =\n  | OrderByDirection\n  | OrderByModifiersCallbackExpression\n\nexport type OrderByDirection = 'asc' | 'desc'\n\nexport function isOrderByDirection(thing: unknown): thing is OrderByDirection {\n  return thing === 'asc' || thing === 'desc'\n}\n\nexport type OrderByModifiersCallbackExpression = (\n  builder: OrderByItemBuilder,\n) => OrderByItemBuilder\n\n// TODO: remove in v0.29\n/**\n * @deprecated performance reasons, use {@link OrderByExpression} instead.\n */\nexport type DirectedOrderByStringReference<DB, TB extends keyof DB, O> = `${\n  | StringReference<DB, TB>\n  | (keyof O & string)} ${OrderByDirection}`\n\n// TODO: remove in v0.29\n/**\n * @deprecated replaced with {@link OrderByModifiers}\n */\nexport type OrderByDirectionExpression = OrderByDirection | Expression<any>\n\n// TODO: remove in v0.29\n/**\n * @deprecated use {@link OrderByExpression} instead.\n */\nexport type UndirectedOrderByExpression<DB, TB extends keyof DB, O> =\n  | ReferenceExpression<DB, TB>\n  | (keyof O & string)\n\nexport function parseOrderBy(args: any[]): OrderByItemNode[] {\n  if (args.length === 2) {\n    return [parseOrderByItem(args[0], args[1])]\n  }\n\n  if (args.length === 1) {\n    const [orderBy] = args\n\n    if (Array.isArray(orderBy)) {\n      logOnce(\n        'orderBy(array) is deprecated, use multiple orderBy calls instead.',\n      )\n\n      return orderBy.map((item) => parseOrderByItem(item))\n    }\n\n    return [parseOrderByItem(orderBy)]\n  }\n\n  throw new Error(\n    `Invalid number of arguments at order by! expected 1-2, received ${args.length}`,\n  )\n}\n\nexport function parseOrderByItem(\n  expr: OrderByExpression<any, any, any>,\n  modifiers?: OrderByModifiers,\n): OrderByItemNode {\n  const parsedRef = parseOrderByExpression(expr)\n\n  if (OrderByItemNode.is(parsedRef)) {\n    if (modifiers) {\n      throw new Error('Cannot specify direction twice!')\n    }\n\n    return parsedRef\n  }\n\n  return parseOrderByWithModifiers(parsedRef, modifiers)\n}\n\nfunction parseOrderByExpression(\n  expr: OrderByExpression<any, any, any>,\n): OperationNode {\n  if (isExpressionOrFactory(expr)) {\n    return parseExpression(expr)\n  }\n\n  if (isDynamicReferenceBuilder(expr)) {\n    return expr.toOperationNode()\n  }\n\n  const [ref, direction] = expr.split(' ')\n\n  if (direction) {\n    logOnce(\n      \"`orderBy('column asc')` is deprecated. Use `orderBy('column', 'asc')` instead.\",\n    )\n\n    return parseOrderByWithModifiers(parseStringReference(ref), direction)\n  }\n\n  return parseStringReference(expr)\n}\n\nfunction parseOrderByWithModifiers(\n  expr: OperationNode,\n  modifiers:\n    | string\n    | OrderByModifiersCallbackExpression\n    // TODO: remove in v0.29\n    | Expression<any>\n    | undefined,\n): OrderByItemNode {\n  if (typeof modifiers === 'string') {\n    if (!isOrderByDirection(modifiers)) {\n      throw new Error(`Invalid order by direction: ${modifiers}`)\n    }\n\n    return OrderByItemNode.create(expr, RawNode.createWithSql(modifiers))\n  }\n\n  if (isExpression(modifiers)) {\n    logOnce(\n      \"`orderBy(..., expr)` is deprecated. Use `orderBy(..., 'asc')` or `orderBy(..., (ob) => ...)` instead.\",\n    )\n\n    return OrderByItemNode.create(expr, modifiers.toOperationNode())\n  }\n\n  const node = OrderByItemNode.create(expr)\n\n  if (!modifiers) {\n    return node\n  }\n\n  return modifiers(new OrderByItemBuilder({ node })).toOperationNode()\n}\n"
  },
  {
    "path": "src/parser/parse-utils.ts",
    "content": "import { JoinNode, type JoinType } from '../operation-node/join-node.js'\nimport { OverNode } from '../operation-node/over-node.js'\nimport { SelectQueryNode } from '../operation-node/select-query-node.js'\nimport { JoinBuilder } from '../query-builder/join-builder.js'\nimport { OverBuilder } from '../query-builder/over-builder.js'\nimport {\n  type SelectQueryBuilder,\n  createSelectQueryBuilder as newSelectQueryBuilder,\n} from '../query-builder/select-query-builder.js'\nimport { QueryCreator } from '../query-creator.js'\nimport { NOOP_QUERY_EXECUTOR } from '../query-executor/noop-query-executor.js'\nimport { createQueryId } from '../util/query-id.js'\nimport {\n  parseTableExpression,\n  parseTableExpressionOrList,\n  type TableExpression,\n} from './table-parser.js'\n\nexport function createSelectQueryBuilder(): SelectQueryBuilder<any, any, any> {\n  return newSelectQueryBuilder({\n    queryId: createQueryId(),\n    executor: NOOP_QUERY_EXECUTOR,\n    queryNode: SelectQueryNode.createFrom(parseTableExpressionOrList([])),\n  })\n}\n\nexport function createQueryCreator(): QueryCreator<any> {\n  return new QueryCreator({\n    executor: NOOP_QUERY_EXECUTOR,\n  })\n}\n\nexport function createJoinBuilder(\n  joinType: JoinType,\n  table: TableExpression<any, any>,\n): JoinBuilder<any, any> {\n  return new JoinBuilder({\n    joinNode: JoinNode.create(joinType, parseTableExpression(table)),\n  })\n}\n\nexport function createOverBuilder(): OverBuilder<any, any> {\n  return new OverBuilder({\n    overNode: OverNode.create(),\n  })\n}\n"
  },
  {
    "path": "src/parser/partition-by-parser.ts",
    "content": "import type { DynamicReferenceBuilder } from '../dynamic/dynamic-reference-builder.js'\nimport { PartitionByItemNode } from '../operation-node/partition-by-item-node.js'\nimport type { SimpleReferenceExpressionNode } from '../operation-node/simple-reference-expression-node.js'\nimport {\n  parseReferenceExpressionOrList,\n  type StringReference,\n} from './reference-parser.js'\n\nexport type PartitionByExpression<DB, TB extends keyof DB> =\n  | StringReference<DB, TB>\n  | DynamicReferenceBuilder<any>\n\nexport type PartitionByExpressionOrList<DB, TB extends keyof DB> =\n  | ReadonlyArray<PartitionByExpression<DB, TB>>\n  | PartitionByExpression<DB, TB>\n\nexport function parsePartitionBy(\n  partitionBy: PartitionByExpressionOrList<any, any>,\n): PartitionByItemNode[] {\n  return (\n    parseReferenceExpressionOrList(\n      partitionBy,\n    ) as SimpleReferenceExpressionNode[]\n  ).map(PartitionByItemNode.create)\n}\n"
  },
  {
    "path": "src/parser/reference-parser.ts",
    "content": "import { AliasNode } from '../operation-node/alias-node.js'\nimport { ColumnNode } from '../operation-node/column-node.js'\nimport { ReferenceNode } from '../operation-node/reference-node.js'\nimport { TableNode } from '../operation-node/table-node.js'\nimport { isReadonlyArray, isString } from '../util/object-utils.js'\nimport type {\n  AnyColumn,\n  AnyColumnWithTable,\n  ExtractColumnType,\n} from '../util/type-utils.js'\nimport type { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js'\nimport {\n  parseExpression,\n  type ExpressionOrFactory,\n  isExpressionOrFactory,\n} from './expression-parser.js'\nimport type { DynamicReferenceBuilder } from '../dynamic/dynamic-reference-builder.js'\nimport type { SelectType, UpdateType } from '../util/column-type.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport type { Expression } from '../expression/expression.js'\nimport type { SimpleReferenceExpressionNode } from '../operation-node/simple-reference-expression-node.js'\nimport {\n  type OrderByDirection,\n  isOrderByDirection,\n  parseOrderBy,\n} from './order-by-parser.js'\nimport {\n  type JSONOperatorWith$,\n  OperatorNode,\n  isJSONOperator,\n} from '../operation-node/operator-node.js'\nimport { JSONReferenceNode } from '../operation-node/json-reference-node.js'\nimport { JSONOperatorChainNode } from '../operation-node/json-operator-chain-node.js'\nimport { JSONPathNode } from '../operation-node/json-path-node.js'\n\nexport type StringReference<DB, TB extends keyof DB> =\n  | AnyColumn<DB, TB>\n  | AnyColumnWithTable<DB, TB>\n\nexport type SimpleReferenceExpression<DB, TB extends keyof DB> =\n  | StringReference<DB, TB>\n  | DynamicReferenceBuilder<any>\n\nexport type ReferenceExpression<DB, TB extends keyof DB> =\n  | SimpleReferenceExpression<DB, TB>\n  | ExpressionOrFactory<DB, TB, any>\n\nexport type ReferenceExpressionOrList<DB, TB extends keyof DB> =\n  | ReferenceExpression<DB, TB>\n  | ReadonlyArray<ReferenceExpression<DB, TB>>\n\nexport type ExtractTypeFromReferenceExpression<\n  DB,\n  TB extends keyof DB,\n  RE,\n  DV = unknown,\n> = SelectType<ExtractRawTypeFromReferenceExpression<DB, TB, RE, DV>>\n\nexport type ExtractRawTypeFromReferenceExpression<\n  DB,\n  TB extends keyof DB,\n  RE,\n  DV = unknown,\n> = RE extends string\n  ? ExtractTypeFromStringReference<DB, TB, RE>\n  : RE extends SelectQueryBuilderExpression<infer O>\n    ? O[keyof O] | null\n    : RE extends (qb: any) => SelectQueryBuilderExpression<infer O>\n      ? O[keyof O] | null\n      : RE extends Expression<infer O>\n        ? O\n        : RE extends (qb: any) => Expression<infer O>\n          ? O\n          : DV\n\nexport type ExtractTypeFromStringReference<\n  DB,\n  TB extends keyof DB,\n  RE extends string,\n  DV = unknown,\n> = RE extends `${infer SC}.${infer T}.${infer C}`\n  ? `${SC}.${T}` extends TB\n    ? C extends keyof DB[`${SC}.${T}`]\n      ? DB[`${SC}.${T}`][C]\n      : never\n    : never\n  : RE extends `${infer T}.${infer C}`\n    ? T extends TB\n      ? C extends keyof DB[T]\n        ? DB[T][C]\n        : never\n      : never\n    : RE extends AnyColumn<DB, TB>\n      ? ExtractColumnType<DB, TB, RE>\n      : DV\n\nexport type OrderedColumnName<C extends string> =\n  C extends `${string} ${infer O}`\n    ? O extends OrderByDirection\n      ? C\n      : never\n    : C\n\nexport type ExtractColumnNameFromOrderedColumnName<C extends string> =\n  C extends `${infer CL} ${infer O}`\n    ? O extends OrderByDirection\n      ? CL\n      : never\n    : C\n\nexport function parseSimpleReferenceExpression(\n  exp: SimpleReferenceExpression<any, any>,\n): SimpleReferenceExpressionNode {\n  if (isString(exp)) {\n    return parseStringReference(exp)\n  }\n\n  return exp.toOperationNode()\n}\n\nexport function parseReferenceExpressionOrList(\n  arg: ReferenceExpressionOrList<any, any>,\n): OperationNode[] {\n  if (isReadonlyArray(arg)) {\n    return arg.map((it) => parseReferenceExpression(it))\n  } else {\n    return [parseReferenceExpression(arg)]\n  }\n}\n\nexport function parseReferenceExpression(\n  exp: ReferenceExpression<any, any>,\n): OperationNode {\n  if (isExpressionOrFactory(exp)) {\n    return parseExpression(exp)\n  }\n\n  return parseSimpleReferenceExpression(exp)\n}\n\nexport function parseJSONReference(\n  ref: string,\n  op: JSONOperatorWith$,\n): JSONReferenceNode {\n  const referenceNode = parseStringReference(ref)\n\n  if (isJSONOperator(op)) {\n    return JSONReferenceNode.create(\n      referenceNode,\n      JSONOperatorChainNode.create(OperatorNode.create(op)),\n    )\n  }\n\n  const opWithoutLastChar = op.slice(0, -1)\n\n  if (isJSONOperator(opWithoutLastChar)) {\n    return JSONReferenceNode.create(\n      referenceNode,\n      JSONPathNode.create(OperatorNode.create(opWithoutLastChar)),\n    )\n  }\n\n  throw new Error(`Invalid JSON operator: ${op}`)\n}\n\nexport function parseStringReference(ref: string): ReferenceNode {\n  const COLUMN_SEPARATOR = '.'\n\n  if (!ref.includes(COLUMN_SEPARATOR)) {\n    return ReferenceNode.create(ColumnNode.create(ref))\n  }\n\n  const parts = ref.split(COLUMN_SEPARATOR).map(trim)\n\n  if (parts.length === 3) {\n    return parseStringReferenceWithTableAndSchema(parts)\n  }\n\n  if (parts.length === 2) {\n    return parseStringReferenceWithTable(parts)\n  }\n\n  throw new Error(`invalid column reference ${ref}`)\n}\n\nexport function parseAliasedStringReference(\n  ref: string,\n): SimpleReferenceExpressionNode | AliasNode {\n  const ALIAS_SEPARATOR = ' as '\n\n  if (ref.includes(ALIAS_SEPARATOR)) {\n    const [columnRef, alias] = ref.split(ALIAS_SEPARATOR).map(trim)\n\n    return AliasNode.create(\n      parseStringReference(columnRef),\n      IdentifierNode.create(alias),\n    )\n  } else {\n    return parseStringReference(ref)\n  }\n}\n\nexport function parseColumnName(column: AnyColumn<any, any>): ColumnNode {\n  return ColumnNode.create(column)\n}\n\nexport function parseOrderedColumnName(column: string): OperationNode {\n  const ORDER_SEPARATOR = ' '\n\n  if (column.includes(ORDER_SEPARATOR)) {\n    const [columnName, order] = column.split(ORDER_SEPARATOR).map(trim)\n\n    if (!isOrderByDirection(order)) {\n      throw new Error(\n        `invalid order direction \"${order}\" next to \"${columnName}\"`,\n      )\n    }\n\n    return parseOrderBy([columnName, order])[0]\n  } else {\n    return parseColumnName(column)\n  }\n}\n\nfunction parseStringReferenceWithTableAndSchema(\n  parts: string[],\n): ReferenceNode {\n  const [schema, table, column] = parts\n\n  return ReferenceNode.create(\n    ColumnNode.create(column),\n    TableNode.createWithSchema(schema, table),\n  )\n}\n\nfunction parseStringReferenceWithTable(parts: string[]): ReferenceNode {\n  const [table, column] = parts\n\n  return ReferenceNode.create(\n    ColumnNode.create(column),\n    TableNode.create(table),\n  )\n}\n\nfunction trim(str: string): string {\n  return str.trim()\n}\n"
  },
  {
    "path": "src/parser/returning-parser.ts",
    "content": "import type { DeleteResult } from '../query-builder/delete-result.js'\nimport type { InsertResult } from '../query-builder/insert-result.js'\nimport type { MergeResult } from '../query-builder/merge-result.js'\nimport type { UpdateResult } from '../query-builder/update-result.js'\nimport type {\n  Selection,\n  AllSelection,\n  CallbackSelection,\n} from './select-parser.js'\n\nexport type ReturningRow<DB, TB extends keyof DB, O, SE> = O extends\n  | InsertResult\n  | DeleteResult\n  | UpdateResult\n  | MergeResult\n  ? Selection<DB, TB, SE>\n  : O & Selection<DB, TB, SE>\n\nexport type ReturningCallbackRow<DB, TB extends keyof DB, O, CB> = O extends\n  | InsertResult\n  | DeleteResult\n  | UpdateResult\n  | MergeResult\n  ? CallbackSelection<DB, TB, CB>\n  : O & CallbackSelection<DB, TB, CB>\n\nexport type ReturningAllRow<DB, TB extends keyof DB, O> = O extends\n  | InsertResult\n  | DeleteResult\n  | UpdateResult\n  | MergeResult\n  ? AllSelection<DB, TB>\n  : O & AllSelection<DB, TB>\n"
  },
  {
    "path": "src/parser/savepoint-parser.ts",
    "content": "import { IdentifierNode } from '../operation-node/identifier-node.js'\nimport { RawNode } from '../operation-node/raw-node.js'\n\nexport type RollbackToSavepoint<\n  S extends string[],\n  SN extends S[number],\n> = S extends [...infer L, infer R]\n  ? R extends SN\n    ? S\n    : RollbackToSavepoint<L extends string[] ? L : never, SN>\n  : never\n\nexport type ReleaseSavepoint<\n  S extends string[],\n  SN extends S[number],\n> = S extends [...infer L, infer R]\n  ? R extends SN\n    ? L\n    : ReleaseSavepoint<L extends string[] ? L : never, SN>\n  : never\n\nexport function parseSavepointCommand(\n  command: string,\n  savepointName: string,\n): RawNode {\n  return RawNode.createWithChildren([\n    RawNode.createWithSql(`${command} `),\n    IdentifierNode.create(savepointName), // ensures savepointName gets sanitized\n  ])\n}\n"
  },
  {
    "path": "src/parser/select-from-parser.ts",
    "content": "import type { SelectQueryBuilder } from '../query-builder/select-query-builder.js'\nimport type { ShallowRecord } from '../util/type-utils.js'\nimport type {\n  ExtractTableAlias,\n  From,\n  FromTables,\n  TableExpressionOrList,\n} from './table-parser.js'\n\nexport type SelectFrom<\n  DB,\n  TB extends keyof DB,\n  TE extends TableExpressionOrList<DB, TB>,\n> = [TE] extends [keyof DB]\n  ? // This branch creates a good-looking type for the most common case:\n    // selectFrom('person') --> SelectQueryBuilder<DB, 'person', {}>.\n    // ExtractTableAlias is needed for the case where DB == any. Without it:\n    // selectFrom('person as p') --> SelectQueryBuilder<DB, 'person as p', {}>\n    SelectQueryBuilder<DB, TB | ExtractTableAlias<DB, TE>, {}>\n  : // This branch creates a good-looking type for common aliased case:\n    // selectFrom('person as p') --> SelectQueryBuilder<DB & { p: Person }, 'p', {}>.\n    [TE] extends [`${infer T} as ${infer A}`]\n    ? T extends keyof DB\n      ? SelectQueryBuilder<DB & ShallowRecord<A, DB[T]>, TB | A, {}>\n      : never\n    : TE extends ReadonlyArray<infer T>\n      ? SelectQueryBuilder<From<DB, T>, FromTables<DB, TB, T>, {}>\n      : SelectQueryBuilder<From<DB, TE>, FromTables<DB, TB, TE>, {}>\n"
  },
  {
    "path": "src/parser/select-parser.ts",
    "content": "import { isFunction, isReadonlyArray, isString } from '../util/object-utils.js'\nimport type { AliasedSelectQueryBuilder } from '../query-builder/select-query-builder.js'\nimport { SelectionNode } from '../operation-node/selection-node.js'\nimport type {\n  AnyAliasedColumn,\n  AnyAliasedColumnWithTable,\n  AnyColumn,\n  AnyColumnWithTable,\n  DrainOuterGeneric,\n  ExtractColumnType,\n} from '../util/type-utils.js'\nimport { parseAliasedStringReference } from './reference-parser.js'\nimport {\n  type DynamicReferenceBuilder,\n  isDynamicReferenceBuilder,\n} from '../dynamic/dynamic-reference-builder.js'\nimport {\n  type AliasedExpressionOrFactory,\n  parseAliasedExpression,\n} from './expression-parser.js'\nimport type { SelectType } from '../util/column-type.js'\nimport { parseTable } from './table-parser.js'\nimport type { AliasedExpression } from '../expression/expression.js'\nimport {\n  expressionBuilder,\n  type ExpressionBuilder,\n} from '../expression/expression-builder.js'\n\nexport type SelectExpression<DB, TB extends keyof DB> =\n  | AnyAliasedColumnWithTable<DB, TB>\n  | AnyAliasedColumn<DB, TB>\n  | AnyColumnWithTable<DB, TB>\n  | AnyColumn<DB, TB>\n  | DynamicReferenceBuilder<any>\n  | AliasedExpressionOrFactory<DB, TB>\n\nexport type SelectCallback<DB, TB extends keyof DB> = (\n  eb: ExpressionBuilder<DB, TB>,\n) => ReadonlyArray<SelectExpression<DB, TB>>\n\n/**\n * Turns a SelectExpression or a union of them into a selection object.\n */\nexport type Selection<\n  DB,\n  TB extends keyof DB,\n  SE,\n  // Inline version of DrainOuterGeneric for performance reasons.\n  // Don't replace with DrainOuterGeneric!\n> = [DB] extends [unknown]\n  ? {\n      [E in FlattenSelectExpression<SE> as ExtractAliasFromSelectExpression<E>]: SelectType<\n        ExtractTypeFromSelectExpression<DB, TB, E>\n      >\n    }\n  : {}\n\n/**\n * Turns a SelectCallback into a selection object.\n */\nexport type CallbackSelection<DB, TB extends keyof DB, CB> = CB extends (\n  eb: any,\n) => ReadonlyArray<infer SE>\n  ? Selection<DB, TB, SE>\n  : never\n\nexport type SelectArg<\n  DB,\n  TB extends keyof DB,\n  SE extends SelectExpression<DB, TB>,\n> =\n  | SE\n  | ReadonlyArray<SE>\n  | ((eb: ExpressionBuilder<DB, TB>) => ReadonlyArray<SE>)\n\ntype FlattenSelectExpression<SE> =\n  SE extends DynamicReferenceBuilder<infer RA>\n    ? { [R in RA]: DynamicReferenceBuilder<R> }[RA]\n    : SE\n\ntype ExtractAliasFromSelectExpression<SE> = SE extends string\n  ? ExtractAliasFromStringSelectExpression<SE>\n  : SE extends AliasedExpression<any, infer EA>\n    ? EA\n    : SE extends (qb: any) => AliasedExpression<any, infer EA>\n      ? EA\n      : SE extends DynamicReferenceBuilder<infer RA>\n        ? ExtractAliasFromStringSelectExpression<RA>\n        : never\n\ntype ExtractAliasFromStringSelectExpression<SE extends string> =\n  SE extends `${string}.${string}.${string} as ${infer A}`\n    ? A\n    : SE extends `${string}.${string} as ${infer A}`\n      ? A\n      : SE extends `${string} as ${infer A}`\n        ? A\n        : SE extends `${string}.${string}.${infer C}`\n          ? C\n          : SE extends `${string}.${infer C}`\n            ? C\n            : SE\n\ntype ExtractTypeFromSelectExpression<\n  DB,\n  TB extends keyof DB,\n  SE,\n> = SE extends string\n  ? ExtractTypeFromStringSelectExpression<DB, TB, SE>\n  : SE extends AliasedSelectQueryBuilder<infer O, any>\n    ? O[keyof O] | null\n    : SE extends (eb: any) => AliasedSelectQueryBuilder<infer O, any>\n      ? O[keyof O] | null\n      : SE extends AliasedExpression<infer O, any>\n        ? O\n        : SE extends (eb: any) => AliasedExpression<infer O, any>\n          ? O\n          : SE extends DynamicReferenceBuilder<infer RA>\n            ? ExtractTypeFromStringSelectExpression<DB, TB, RA> | undefined\n            : never\n\ntype ExtractTypeFromStringSelectExpression<\n  DB,\n  TB extends keyof DB,\n  SE extends string,\n> = SE extends `${infer SC}.${infer T}.${infer C} as ${string}`\n  ? `${SC}.${T}` extends TB\n    ? C extends keyof DB[`${SC}.${T}`]\n      ? DB[`${SC}.${T}`][C]\n      : never\n    : never\n  : SE extends `${infer T}.${infer C} as ${string}`\n    ? T extends TB\n      ? C extends keyof DB[T]\n        ? DB[T][C]\n        : never\n      : never\n    : SE extends `${infer C} as ${string}`\n      ? C extends AnyColumn<DB, TB>\n        ? ExtractColumnType<DB, TB, C>\n        : never\n      : SE extends `${infer SC}.${infer T}.${infer C}`\n        ? `${SC}.${T}` extends TB\n          ? C extends keyof DB[`${SC}.${T}`]\n            ? DB[`${SC}.${T}`][C]\n            : never\n          : never\n        : SE extends `${infer T}.${infer C}`\n          ? T extends TB\n            ? C extends keyof DB[T]\n              ? DB[T][C]\n              : never\n            : never\n          : SE extends AnyColumn<DB, TB>\n            ? ExtractColumnType<DB, TB, SE>\n            : never\n\nexport type AllSelection<DB, TB extends keyof DB> = DrainOuterGeneric<{\n  [C in AnyColumn<DB, TB>]: {\n    [T in TB]: SelectType<C extends keyof DB[T] ? DB[T][C] : never>\n  }[TB]\n}>\n\nexport function parseSelectArg(\n  selection: SelectArg<any, any, SelectExpression<any, any>>,\n): SelectionNode[] {\n  if (isFunction(selection)) {\n    return parseSelectArg(selection(expressionBuilder()))\n  } else if (isReadonlyArray(selection)) {\n    return selection.map((it) => parseSelectExpression(it))\n  } else {\n    return [parseSelectExpression(selection)]\n  }\n}\n\nfunction parseSelectExpression(\n  selection: SelectExpression<any, any>,\n): SelectionNode {\n  if (isString(selection)) {\n    return SelectionNode.create(parseAliasedStringReference(selection))\n  } else if (isDynamicReferenceBuilder(selection)) {\n    return SelectionNode.create(selection.toOperationNode())\n  } else {\n    return SelectionNode.create(parseAliasedExpression(selection))\n  }\n}\n\nexport function parseSelectAll(table?: string | string[]): SelectionNode[] {\n  if (!table) {\n    return [SelectionNode.createSelectAll()]\n  } else if (Array.isArray(table)) {\n    return table.map(parseSelectAllArg)\n  } else {\n    return [parseSelectAllArg(table)]\n  }\n}\n\nfunction parseSelectAllArg(table: string): SelectionNode {\n  if (isString(table)) {\n    return SelectionNode.createSelectAllFromTable(parseTable(table))\n  }\n\n  throw new Error(\n    `invalid value selectAll expression: ${JSON.stringify(table)}`,\n  )\n}\n"
  },
  {
    "path": "src/parser/set-operation-parser.ts",
    "content": "import {\n  type ExpressionBuilder,\n  createExpressionBuilder,\n} from '../expression/expression-builder.js'\nimport type { Expression } from '../expression/expression.js'\nimport {\n  type SetOperator,\n  SetOperationNode,\n} from '../operation-node/set-operation-node.js'\nimport { isFunction, isReadonlyArray } from '../util/object-utils.js'\nimport { parseExpression } from './expression-parser.js'\n\nexport type SetOperandExpression<DB, O> =\n  | Expression<O>\n  | ReadonlyArray<Expression<O>>\n  | ((\n      eb: ExpressionBuilder<DB, never>,\n    ) => Expression<O> | ReadonlyArray<Expression<O>>)\n\nexport function parseSetOperations(\n  operator: SetOperator,\n  expression: SetOperandExpression<any, any>,\n  all: boolean,\n) {\n  if (isFunction(expression)) {\n    expression = expression(createExpressionBuilder())\n  }\n\n  if (!isReadonlyArray(expression)) {\n    expression = [expression]\n  }\n\n  return expression.map((expr) =>\n    SetOperationNode.create(operator, parseExpression(expr), all),\n  )\n}\n"
  },
  {
    "path": "src/parser/table-parser.ts",
    "content": "import { isReadonlyArray, isString } from '../util/object-utils.js'\nimport { AliasNode } from '../operation-node/alias-node.js'\nimport { TableNode } from '../operation-node/table-node.js'\nimport {\n  type AliasedExpressionOrFactory,\n  parseAliasedExpression,\n} from './expression-parser.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport type { AliasedExpression } from '../expression/expression.js'\nimport type { DrainOuterGeneric } from '../util/type-utils.js'\nimport {\n  type AliasedDynamicTableBuilder,\n  isAliasedDynamicTableBuilder,\n} from '../dynamic/dynamic-table-builder.js'\n\nexport type TableExpression<DB, TB extends keyof DB> =\n  | AnyAliasedTable<DB>\n  | AnyTable<DB>\n  | AliasedExpressionOrFactory<DB, TB>\n  | AliasedDynamicTableBuilder<any, any>\n\nexport type TableExpressionOrList<DB, TB extends keyof DB> =\n  | TableExpression<DB, TB>\n  | ReadonlyArray<TableExpression<DB, TB>>\n\nexport type SimpleTableReference<DB> = AnyAliasedTable<DB> | AnyTable<DB>\nexport type AnyAliasedTable<DB> = `${AnyTable<DB>} as ${string}`\nexport type AnyTable<DB> = keyof DB & string\n\nexport type From<DB, TE> = DrainOuterGeneric<{\n  [C in\n    | keyof DB\n    | ExtractAliasFromTableExpression<\n        DB,\n        TE\n      >]: C extends ExtractAliasFromTableExpression<DB, TE>\n    ? ExtractRowTypeFromTableExpression<DB, TE, C>\n    : C extends keyof DB\n      ? DB[C]\n      : never\n}>\n\nexport type FromTables<DB, TB extends keyof DB, TE> = DrainOuterGeneric<\n  TB | ExtractAliasFromTableExpression<DB, TE>\n>\n\nexport type ExtractTableAlias<DB, TE> = TE extends `${string} as ${infer TA}`\n  ? TA extends keyof DB\n    ? TA\n    : never\n  : TE extends keyof DB\n    ? TE\n    : never\n\ntype ExtractAliasFromTableExpression<DB, TE> = TE extends string\n  ? TE extends `${string} as ${infer TA}`\n    ? TA\n    : TE extends keyof DB\n      ? TE\n      : never\n  : TE extends AliasedExpression<any, infer QA>\n    ? QA\n    : TE extends (qb: any) => AliasedExpression<any, infer QA>\n      ? QA\n      : TE extends AliasedDynamicTableBuilder<any, infer DA>\n        ? DA\n        : never\n\ntype ExtractRowTypeFromTableExpression<\n  DB,\n  TE,\n  A extends keyof any,\n> = TE extends `${infer T} as ${infer TA}`\n  ? TA extends A\n    ? T extends keyof DB\n      ? DB[T]\n      : never\n    : never\n  : TE extends A\n    ? TE extends keyof DB\n      ? DB[TE]\n      : never\n    : TE extends AliasedExpression<infer O, infer QA>\n      ? QA extends A\n        ? O\n        : never\n      : TE extends (qb: any) => AliasedExpression<infer O, infer QA>\n        ? QA extends A\n          ? O\n          : never\n        : TE extends AliasedDynamicTableBuilder<infer T, infer DA>\n          ? DA extends A\n            ? T extends keyof DB\n              ? DB[T]\n              : never\n            : never\n          : never\n\nexport function parseTableExpressionOrList(\n  table: TableExpressionOrList<any, any>,\n): OperationNode[] {\n  if (isReadonlyArray(table)) {\n    return table.map((it) => parseTableExpression(it))\n  } else {\n    return [parseTableExpression(table)]\n  }\n}\n\nexport function parseTableExpression(\n  table: TableExpression<any, any>,\n): OperationNode {\n  if (isString(table)) {\n    return parseAliasedTable(table)\n  } else if (isAliasedDynamicTableBuilder(table)) {\n    return table.toOperationNode()\n  } else {\n    return parseAliasedExpression(table)\n  }\n}\n\nexport function parseAliasedTable(from: string): TableNode | AliasNode {\n  const ALIAS_SEPARATOR = ' as '\n\n  if (from.includes(ALIAS_SEPARATOR)) {\n    const [table, alias] = from.split(ALIAS_SEPARATOR).map(trim)\n\n    return AliasNode.create(parseTable(table), IdentifierNode.create(alias))\n  } else {\n    return parseTable(from)\n  }\n}\n\nexport function parseTable(from: string): TableNode {\n  const SCHEMA_SEPARATOR = '.'\n\n  if (from.includes(SCHEMA_SEPARATOR)) {\n    const [schema, table] = from.split(SCHEMA_SEPARATOR).map(trim)\n\n    return TableNode.createWithSchema(schema, table)\n  } else {\n    return TableNode.create(from)\n  }\n}\n\nfunction trim(str: string): string {\n  return str.trim()\n}\n"
  },
  {
    "path": "src/parser/top-parser.ts",
    "content": "import { type TopModifier, TopNode } from '../operation-node/top-node.js'\nimport { isBigInt, isNumber, isUndefined } from '../util/object-utils.js'\n\nexport function parseTop(\n  expression: number | bigint,\n  modifiers?: TopModifier,\n): TopNode {\n  if (!isNumber(expression) && !isBigInt(expression)) {\n    throw new Error(`Invalid top expression: ${expression}`)\n  }\n\n  if (!isUndefined(modifiers) && !isTopModifiers(modifiers)) {\n    throw new Error(`Invalid top modifiers: ${modifiers}`)\n  }\n\n  return TopNode.create(expression, modifiers)\n}\n\nfunction isTopModifiers(modifiers: string): modifiers is TopModifier {\n  return (\n    modifiers === 'percent' ||\n    modifiers === 'with ties' ||\n    modifiers === 'percent with ties'\n  )\n}\n"
  },
  {
    "path": "src/parser/tuple-parser.ts",
    "content": "import type { DrainOuterGeneric } from '../util/type-utils.js'\nimport type { ExtractTypeFromReferenceExpression } from './reference-parser.js'\nimport type { ExtractTypeFromValueExpression } from './value-parser.js'\n\nexport type RefTuple2<DB, TB extends keyof DB, R1, R2> = DrainOuterGeneric<\n  [\n    ExtractTypeFromReferenceExpression<DB, TB, R1>,\n    ExtractTypeFromReferenceExpression<DB, TB, R2>,\n  ]\n>\n\nexport type RefTuple3<DB, TB extends keyof DB, R1, R2, R3> = DrainOuterGeneric<\n  [\n    ExtractTypeFromReferenceExpression<DB, TB, R1>,\n    ExtractTypeFromReferenceExpression<DB, TB, R2>,\n    ExtractTypeFromReferenceExpression<DB, TB, R3>,\n  ]\n>\n\nexport type RefTuple4<\n  DB,\n  TB extends keyof DB,\n  R1,\n  R2,\n  R3,\n  R4,\n> = DrainOuterGeneric<\n  [\n    ExtractTypeFromReferenceExpression<DB, TB, R1>,\n    ExtractTypeFromReferenceExpression<DB, TB, R2>,\n    ExtractTypeFromReferenceExpression<DB, TB, R3>,\n    ExtractTypeFromReferenceExpression<DB, TB, R4>,\n  ]\n>\n\nexport type RefTuple5<\n  DB,\n  TB extends keyof DB,\n  R1,\n  R2,\n  R3,\n  R4,\n  R5,\n> = DrainOuterGeneric<\n  [\n    ExtractTypeFromReferenceExpression<DB, TB, R1>,\n    ExtractTypeFromReferenceExpression<DB, TB, R2>,\n    ExtractTypeFromReferenceExpression<DB, TB, R3>,\n    ExtractTypeFromReferenceExpression<DB, TB, R4>,\n    ExtractTypeFromReferenceExpression<DB, TB, R5>,\n  ]\n>\n\nexport type ValTuple2<V1, V2> = DrainOuterGeneric<\n  [ExtractTypeFromValueExpression<V1>, ExtractTypeFromValueExpression<V2>]\n>\n\nexport type ValTuple3<V1, V2, V3> = DrainOuterGeneric<\n  [\n    ExtractTypeFromValueExpression<V1>,\n    ExtractTypeFromValueExpression<V2>,\n    ExtractTypeFromValueExpression<V3>,\n  ]\n>\n\nexport type ValTuple4<V1, V2, V3, V4> = DrainOuterGeneric<\n  [\n    ExtractTypeFromValueExpression<V1>,\n    ExtractTypeFromValueExpression<V2>,\n    ExtractTypeFromValueExpression<V3>,\n    ExtractTypeFromValueExpression<V4>,\n  ]\n>\n\nexport type ValTuple5<V1, V2, V3, V4, V5> = DrainOuterGeneric<\n  [\n    ExtractTypeFromValueExpression<V1>,\n    ExtractTypeFromValueExpression<V2>,\n    ExtractTypeFromValueExpression<V3>,\n    ExtractTypeFromValueExpression<V4>,\n    ExtractTypeFromValueExpression<V5>,\n  ]\n>\n"
  },
  {
    "path": "src/parser/unary-operation-parser.ts",
    "content": "import {\n  OperatorNode,\n  type UnaryOperator,\n} from '../operation-node/operator-node.js'\nimport { UnaryOperationNode } from '../operation-node/unary-operation-node.js'\nimport type { ExpressionOrFactory } from './expression-parser.js'\nimport {\n  parseReferenceExpression,\n  type ReferenceExpression,\n} from './reference-parser.js'\n\nexport type ExistsExpression<DB, TB extends keyof DB> = ExpressionOrFactory<\n  DB,\n  TB,\n  any\n>\n\nexport function parseExists(\n  operand: ExistsExpression<any, any>,\n): UnaryOperationNode {\n  return parseUnaryOperation('exists', operand)\n}\n\nexport function parseNotExists(\n  operand: ExistsExpression<any, any>,\n): UnaryOperationNode {\n  return parseUnaryOperation('not exists', operand)\n}\n\nexport function parseUnaryOperation(\n  operator: UnaryOperator,\n  operand: ReferenceExpression<any, any>,\n): UnaryOperationNode {\n  return UnaryOperationNode.create(\n    OperatorNode.create(operator),\n    parseReferenceExpression(operand),\n  )\n}\n"
  },
  {
    "path": "src/parser/update-parser.ts",
    "content": "import type { UpdateQueryBuilder } from '../query-builder/update-query-builder.js'\nimport type { UpdateResult } from '../query-builder/update-result.js'\nimport type { ShallowRecord } from '../util/type-utils.js'\nimport type {\n  ExtractTableAlias,\n  From,\n  FromTables,\n  TableExpressionOrList,\n} from './table-parser.js'\n\nexport type UpdateTable<DB, TE extends TableExpressionOrList<DB, never>> = [\n  TE,\n] extends [keyof DB]\n  ? // This branch creates a good-looking type for the most common case:\n    // updateTable('person') --> UpdateQueryBuilder<DB, 'person', 'person', {}>.\n    // ExtractTableAlias is needed for the case where DB == any. Without it:\n    // updateTable('person as p') --> UpdateQueryBuilder<DB, 'person as p', 'person as p', {}>\n    UpdateQueryBuilder<\n      DB,\n      ExtractTableAlias<DB, TE>,\n      ExtractTableAlias<DB, TE>,\n      UpdateResult\n    >\n  : // This branch creates a good-looking type for common aliased case:\n    // updateTable('person as p') --> UpdateQueryBuilder<DB & { p: Person }, 'p', 'p', {}>.\n    [TE] extends [`${infer T} as ${infer A}`]\n    ? T extends keyof DB\n      ? UpdateQueryBuilder<DB & ShallowRecord<A, DB[T]>, A, A, UpdateResult>\n      : never\n    : TE extends ReadonlyArray<infer T>\n      ? UpdateQueryBuilder<\n          From<DB, T>,\n          FromTables<DB, never, T>,\n          FromTables<DB, never, T>,\n          UpdateResult\n        >\n      : UpdateQueryBuilder<\n          From<DB, TE>,\n          FromTables<DB, never, TE>,\n          FromTables<DB, never, TE>,\n          UpdateResult\n        >\n"
  },
  {
    "path": "src/parser/update-set-parser.ts",
    "content": "import { ColumnNode } from '../operation-node/column-node.js'\nimport { ColumnUpdateNode } from '../operation-node/column-update-node.js'\nimport {\n  expressionBuilder,\n  type ExpressionBuilder,\n} from '../expression/expression-builder.js'\nimport type { UpdateKeys, UpdateType } from '../util/column-type.js'\nimport { isFunction } from '../util/object-utils.js'\nimport { parseValueExpression, type ValueExpression } from './value-parser.js'\nimport {\n  type ExtractRawTypeFromReferenceExpression,\n  parseReferenceExpression,\n  type ReferenceExpression,\n} from './reference-parser.js'\nimport type { AnyColumn, DrainOuterGeneric } from '../util/type-utils.js'\n\nexport type UpdateObject<\n  DB,\n  TB extends keyof DB,\n  UT extends keyof DB = TB,\n> = DrainOuterGeneric<{\n  [C in AnyColumn<DB, UT>]?: {\n    [T in UT]: C extends keyof DB[T]\n      ? ValueExpression<DB, TB, UpdateType<DB[T][C]>> | undefined\n      : never\n  }[UT]\n}>\n\nexport type UpdateObjectFactory<\n  DB,\n  TB extends keyof DB,\n  UT extends keyof DB,\n> = (eb: ExpressionBuilder<DB, TB>) => UpdateObject<DB, TB, UT>\n\nexport type UpdateObjectExpression<\n  DB,\n  TB extends keyof DB,\n  UT extends keyof DB = TB,\n> = UpdateObject<DB, TB, UT> | UpdateObjectFactory<DB, TB, UT>\n\nexport type ExtractUpdateTypeFromReferenceExpression<\n  DB,\n  TB extends keyof DB,\n  RE,\n  DV = unknown,\n> = UpdateType<ExtractRawTypeFromReferenceExpression<DB, TB, RE, DV>>\n\nexport function parseUpdate(\n  ...args:\n    | [UpdateObjectExpression<any, any, any>]\n    | [ReferenceExpression<any, any>, ValueExpression<any, any, any>]\n): ReadonlyArray<ColumnUpdateNode> {\n  if (args.length === 2) {\n    return [\n      ColumnUpdateNode.create(\n        parseReferenceExpression(args[0]),\n        parseValueExpression(args[1]),\n      ),\n    ]\n  }\n\n  return parseUpdateObjectExpression(args[0])\n}\n\nexport function parseUpdateObjectExpression(\n  update: UpdateObjectExpression<any, any, any>,\n): ReadonlyArray<ColumnUpdateNode> {\n  const updateObj = isFunction(update) ? update(expressionBuilder()) : update\n\n  return Object.entries(updateObj)\n    .filter(([_, value]) => value !== undefined)\n    .map(([key, value]) => {\n      return ColumnUpdateNode.create(\n        ColumnNode.create(key),\n        parseValueExpression(value),\n      )\n    })\n}\n"
  },
  {
    "path": "src/parser/value-parser.ts",
    "content": "import { PrimitiveValueListNode } from '../operation-node/primitive-value-list-node.js'\nimport { ValueListNode } from '../operation-node/value-list-node.js'\nimport { ValueNode } from '../operation-node/value-node.js'\nimport {\n  isBoolean,\n  isNull,\n  isNumber,\n  isReadonlyArray,\n} from '../util/object-utils.js'\nimport {\n  parseExpression,\n  type ExpressionOrFactory,\n  isExpressionOrFactory,\n} from './expression-parser.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport type { Expression } from '../expression/expression.js'\nimport type { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js'\n\nexport type ValueExpression<DB, TB extends keyof DB, V> =\n  | V\n  | ExpressionOrFactory<DB, TB, V>\n\nexport type ValueExpressionOrList<DB, TB extends keyof DB, V> =\n  | ValueExpression<DB, TB, V>\n  | ReadonlyArray<ValueExpression<DB, TB, V>>\n\nexport type ExtractTypeFromValueExpressionOrList<VE> =\n  VE extends ReadonlyArray<infer AV>\n    ? ExtractTypeFromValueExpression<AV>\n    : ExtractTypeFromValueExpression<VE>\n\nexport type ExtractTypeFromValueExpression<VE> =\n  VE extends SelectQueryBuilderExpression<Record<string, infer SV>>\n    ? SV\n    : VE extends Expression<infer V>\n      ? V\n      : VE\n\nexport function parseValueExpressionOrList(\n  arg: ValueExpressionOrList<any, any, unknown>,\n): OperationNode {\n  if (isReadonlyArray(arg)) {\n    return parseValueExpressionList(arg)\n  }\n\n  return parseValueExpression(arg)\n}\n\nexport function parseValueExpression(\n  exp: ValueExpression<any, any, unknown>,\n): OperationNode {\n  if (isExpressionOrFactory(exp)) {\n    return parseExpression(exp)\n  }\n\n  return ValueNode.create(exp)\n}\n\nexport function isSafeImmediateValue(\n  value: unknown,\n): value is number | boolean | null {\n  return isNumber(value) || isBoolean(value) || isNull(value)\n}\n\nexport function parseSafeImmediateValue(\n  value: number | boolean | null,\n): ValueNode {\n  if (!isSafeImmediateValue(value)) {\n    throw new Error(`unsafe immediate value ${JSON.stringify(value)}`)\n  }\n\n  return ValueNode.createImmediate(value)\n}\n\nfunction parseValueExpressionList(\n  arg: ReadonlyArray<ValueExpression<any, any, unknown>>,\n): PrimitiveValueListNode | ValueListNode {\n  if (arg.some(isExpressionOrFactory)) {\n    return ValueListNode.create(arg.map((it) => parseValueExpression(it)))\n  }\n\n  return PrimitiveValueListNode.create(arg)\n}\n"
  },
  {
    "path": "src/parser/with-parser.ts",
    "content": "import type { UpdateQueryBuilder } from '../query-builder/update-query-builder.js'\nimport type { DeleteQueryBuilder } from '../query-builder/delete-query-builder.js'\nimport type { InsertQueryBuilder } from '../query-builder/insert-query-builder.js'\nimport { CommonTableExpressionNameNode } from '../operation-node/common-table-expression-name-node.js'\nimport type { QueryCreator } from '../query-creator.js'\nimport type { Expression } from '../expression/expression.js'\nimport type { ShallowRecord } from '../util/type-utils.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport { createQueryCreator } from './parse-utils.js'\nimport { isFunction } from '../util/object-utils.js'\nimport {\n  CTEBuilder,\n  type CTEBuilderCallback,\n} from '../query-builder/cte-builder.js'\nimport { CommonTableExpressionNode } from '../operation-node/common-table-expression-node.js'\n\nexport type CommonTableExpression<DB, CN extends string> = (\n  creator: QueryCreator<DB>,\n) => CommonTableExpressionOutput<DB, CN>\n\nexport type RecursiveCommonTableExpression<DB, CN extends string> = (\n  creator: QueryCreator<\n    DB & {\n      // Recursive CTE can select from itself.\n      [K in ExtractTableFromCommonTableExpressionName<CN>]: ExtractRowFromCommonTableExpressionName<CN>\n    }\n  >,\n) => CommonTableExpressionOutput<DB, CN>\n\nexport type QueryCreatorWithCommonTableExpression<\n  DB,\n  CN extends string,\n  CTE,\n> = QueryCreator<\n  DB & {\n    [K in ExtractTableFromCommonTableExpressionName<CN>]: ExtractRowFromCommonTableExpression<CTE>\n  }\n>\n\ntype CommonTableExpressionOutput<DB, CN extends string> =\n  | Expression<ExtractRowFromCommonTableExpressionName<CN>>\n  | InsertQueryBuilder<DB, any, ExtractRowFromCommonTableExpressionName<CN>>\n  | UpdateQueryBuilder<\n      DB,\n      any,\n      any,\n      ExtractRowFromCommonTableExpressionName<CN>\n    >\n  | DeleteQueryBuilder<DB, any, ExtractRowFromCommonTableExpressionName<CN>>\n\n/**\n * Given a common CommonTableExpression CTE extracts the row type from it.\n *\n * For example a CTE `(db) => db.selectFrom('person').select(['id', 'first_name'])`\n * would result in `Pick<Person, 'id' | 'first_name'>`.\n */\ntype ExtractRowFromCommonTableExpression<CTE> = CTE extends (\n  creator: QueryCreator<any>,\n) => infer Q\n  ? Q extends Expression<infer QO>\n    ? QO\n    : Q extends InsertQueryBuilder<any, any, infer QO>\n      ? QO\n      : Q extends UpdateQueryBuilder<any, any, any, infer QO>\n        ? QO\n        : Q extends DeleteQueryBuilder<any, any, infer QO>\n          ? QO\n          : never\n  : never\n\n/**\n * Extracts 'person' from a string like 'person(id, first_name)'.\n */\ntype ExtractTableFromCommonTableExpressionName<CN extends string> =\n  CN extends `${infer TB}(${string})` ? TB : CN\n\n/**\n * Parses a string like 'person(id, first_name)' into a type:\n *\n * {\n *   id: any,\n *   first_name: any\n * }\n *\n */\ntype ExtractRowFromCommonTableExpressionName<CN extends string> =\n  CN extends `${string}(${infer CL})`\n    ? { [C in ExtractColumnNamesFromColumnList<CL>]: any }\n    : ShallowRecord<string, any>\n\n/**\n * Parses a string like 'id, first_name' into a type 'id' | 'first_name'\n */\ntype ExtractColumnNamesFromColumnList<R extends string> =\n  R extends `${infer C}, ${infer RS}`\n    ? C | ExtractColumnNamesFromColumnList<RS>\n    : R\n\nexport function parseCommonTableExpression(\n  nameOrBuilderCallback: string | CTEBuilderCallback<string>,\n  expression: CommonTableExpression<any, string>,\n): CommonTableExpressionNode {\n  const expressionNode = expression(createQueryCreator()).toOperationNode()\n\n  if (isFunction(nameOrBuilderCallback)) {\n    return nameOrBuilderCallback(\n      cteBuilderFactory(expressionNode),\n    ).toOperationNode()\n  }\n\n  return CommonTableExpressionNode.create(\n    parseCommonTableExpressionName(nameOrBuilderCallback),\n    expressionNode,\n  )\n}\n\nfunction cteBuilderFactory(expressionNode: OperationNode) {\n  return (name: string) => {\n    return new CTEBuilder({\n      node: CommonTableExpressionNode.create(\n        parseCommonTableExpressionName(name),\n        expressionNode,\n      ),\n    })\n  }\n}\n\nfunction parseCommonTableExpressionName(\n  name: string,\n): CommonTableExpressionNameNode {\n  if (name.includes('(')) {\n    const parts = name.split(/[\\(\\)]/)\n    const table = parts[0]\n    const columns = parts[1].split(',').map((it) => it.trim())\n\n    return CommonTableExpressionNameNode.create(table, columns)\n  } else {\n    return CommonTableExpressionNameNode.create(name)\n  }\n}\n"
  },
  {
    "path": "src/plugin/camel-case/camel-case-plugin.ts",
    "content": "import type { QueryResult } from '../../driver/database-connection.js'\nimport type { RootOperationNode } from '../../query-compiler/query-compiler.js'\nimport { isPlainObject } from '../../util/object-utils.js'\nimport type { UnknownRow } from '../../util/type-utils.js'\nimport type {\n  KyselyPlugin,\n  PluginTransformQueryArgs,\n  PluginTransformResultArgs,\n} from '../kysely-plugin.js'\nimport { SnakeCaseTransformer } from './camel-case-transformer.js'\nimport {\n  createCamelCaseMapper,\n  createSnakeCaseMapper,\n  type StringMapper,\n} from './camel-case.js'\n\nexport interface CamelCasePluginOptions {\n  /**\n   * If true, camelCase is transformed into upper case SNAKE_CASE.\n   * For example `fooBar => FOO_BAR` and `FOO_BAR => fooBar`\n   *\n   * Defaults to false.\n   */\n  upperCase?: boolean\n\n  /**\n   * If true, an underscore is added before each digit when converting\n   * camelCase to snake_case. For example `foo12Bar => foo_12_bar` and\n   * `foo_12_bar => foo12Bar`\n   *\n   * Defaults to false.\n   */\n  underscoreBeforeDigits?: boolean\n\n  /**\n   * If true, an underscore is added between consecutive upper case\n   * letters when converting from camelCase to snake_case. For example\n   * `fooBAR => foo_b_a_r` and `foo_b_a_r => fooBAR`.\n   *\n   * Defaults to false.\n   */\n  underscoreBetweenUppercaseLetters?: boolean\n\n  /**\n   * If true, nested object's keys will not be converted to camel case.\n   *\n   * Defaults to false.\n   */\n  maintainNestedObjectKeys?: boolean\n}\n\n/**\n * A plugin that converts snake_case identifiers in the database into\n * camelCase in the JavaScript side.\n *\n * For example let's assume we have a table called `person_table`\n * with columns `first_name` and `last_name` in the database. When\n * using `CamelCasePlugin` we would setup Kysely like this:\n *\n * ```ts\n * import * as Sqlite from 'better-sqlite3'\n * import { CamelCasePlugin, Kysely, SqliteDialect } from 'kysely'\n *\n * interface CamelCasedDatabase {\n *   userMetadata: {\n *     firstName: string\n *     lastName: string\n *   }\n * }\n *\n * const db = new Kysely<CamelCasedDatabase>({\n *   dialect: new SqliteDialect({\n *     database: new Sqlite(':memory:'),\n *   }),\n *   plugins: [new CamelCasePlugin()],\n * })\n *\n * const person = await db.selectFrom('userMetadata')\n *   .where('firstName', '=', 'Arnold')\n *   .select(['firstName', 'lastName'])\n *   .executeTakeFirst()\n *\n * if (person) {\n *   console.log(person.firstName)\n * }\n * ```\n *\n * The generated SQL (SQLite):\n *\n * ```sql\n * select \"first_name\", \"last_name\" from \"user_metadata\" where \"first_name\" = ?\n * ```\n *\n * As you can see from the example, __everything__ needs to be defined\n * in camelCase in the TypeScript code: table names, columns, schemas,\n * __everything__. When using the `CamelCasePlugin` Kysely works as if\n * the database was defined in camelCase.\n *\n * There are various options you can give to the plugin to modify\n * the way identifiers are converted. See {@link CamelCasePluginOptions}.\n * If those options are not enough, you can override this plugin's\n * `snakeCase` and `camelCase` methods to make the conversion exactly\n * the way you like:\n *\n * ```ts\n * class MyCamelCasePlugin extends CamelCasePlugin {\n *   protected override snakeCase(str: string): string {\n *     // ...\n *\n *     return str\n *   }\n *\n *   protected override camelCase(str: string): string {\n *     // ...\n *\n *     return str\n *   }\n * }\n * ```\n */\nexport class CamelCasePlugin implements KyselyPlugin {\n  readonly #camelCase: StringMapper\n  readonly #snakeCase: StringMapper\n  readonly #snakeCaseTransformer: SnakeCaseTransformer\n\n  constructor(readonly opt: CamelCasePluginOptions = {}) {\n    this.#camelCase = createCamelCaseMapper(opt)\n    this.#snakeCase = createSnakeCaseMapper(opt)\n\n    this.#snakeCaseTransformer = new SnakeCaseTransformer(\n      this.snakeCase.bind(this),\n    )\n  }\n\n  transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n    return this.#snakeCaseTransformer.transformNode(args.node, args.queryId)\n  }\n\n  async transformResult(\n    args: PluginTransformResultArgs,\n  ): Promise<QueryResult<UnknownRow>> {\n    if (args.result.rows && Array.isArray(args.result.rows)) {\n      return {\n        ...args.result,\n        rows: args.result.rows.map((row) => this.mapRow(row)),\n      }\n    }\n\n    return args.result\n  }\n\n  protected mapRow(row: UnknownRow): UnknownRow {\n    return Object.keys(row).reduce<UnknownRow>((obj, key) => {\n      let value = row[key]\n\n      if (Array.isArray(value)) {\n        value = value.map((it) => (canMap(it, this.opt) ? this.mapRow(it) : it))\n      } else if (canMap(value, this.opt)) {\n        value = this.mapRow(value)\n      }\n\n      obj[this.camelCase(key)] = value\n      return obj\n    }, {})\n  }\n\n  protected snakeCase(str: string): string {\n    return this.#snakeCase(str)\n  }\n\n  protected camelCase(str: string): string {\n    return this.#camelCase(str)\n  }\n}\n\nfunction canMap(\n  obj: unknown,\n  opt: CamelCasePluginOptions,\n): obj is Record<string, unknown> {\n  return isPlainObject(obj) && !opt?.maintainNestedObjectKeys\n}\n"
  },
  {
    "path": "src/plugin/camel-case/camel-case-transformer.ts",
    "content": "import type { IdentifierNode } from '../../operation-node/identifier-node.js'\nimport { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js'\nimport type { QueryId } from '../../util/query-id.js'\nimport type { StringMapper } from './camel-case.js'\n\nexport class SnakeCaseTransformer extends OperationNodeTransformer {\n  readonly #snakeCase: StringMapper\n\n  constructor(snakeCase: StringMapper) {\n    super()\n    this.#snakeCase = snakeCase\n  }\n\n  protected override transformIdentifier(\n    node: IdentifierNode,\n    queryId: QueryId,\n  ): IdentifierNode {\n    node = super.transformIdentifier(node, queryId)\n\n    return {\n      ...node,\n      name: this.#snakeCase(node.name),\n    }\n  }\n}\n"
  },
  {
    "path": "src/plugin/camel-case/camel-case.ts",
    "content": "export type StringMapper = (str: string) => string\n\n/**\n * Creates a function that transforms camel case strings to snake case.\n */\nexport function createSnakeCaseMapper({\n  upperCase = false,\n  underscoreBeforeDigits = false,\n  underscoreBetweenUppercaseLetters = false,\n} = {}): StringMapper {\n  return memoize((str: string): string => {\n    if (str.length === 0) {\n      return str\n    }\n\n    const upper = str.toUpperCase()\n    const lower = str.toLowerCase()\n\n    let out = lower[0]\n\n    for (let i = 1, l = str.length; i < l; ++i) {\n      const char = str[i]\n      const prevChar = str[i - 1]\n\n      const upperChar = upper[i]\n      const prevUpperChar = upper[i - 1]\n\n      const lowerChar = lower[i]\n      const prevLowerChar = lower[i - 1]\n\n      // If underScoreBeforeDigits is true then, well, insert an underscore\n      // before digits :). Only the first digit gets an underscore if\n      // there are multiple.\n      if (\n        underscoreBeforeDigits &&\n        isDigit(char) &&\n        !isDigit(prevChar) &&\n        !out.endsWith('_')\n      ) {\n        out += '_' + char\n        continue\n      }\n\n      // Test if `char` is an upper-case character and that the character\n      // actually has different upper and lower case versions.\n      if (char === upperChar && upperChar !== lowerChar) {\n        const prevCharacterIsUppercase =\n          prevChar === prevUpperChar && prevUpperChar !== prevLowerChar\n\n        // If underscoreBetweenUppercaseLetters is true, we always place an underscore\n        // before consecutive uppercase letters (e.g. \"fooBAR\" becomes \"foo_b_a_r\").\n        // Otherwise, we don't (e.g. \"fooBAR\" becomes \"foo_bar\").\n        if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {\n          out += '_' + lowerChar\n        } else {\n          out += lowerChar\n        }\n      } else {\n        out += char\n      }\n    }\n\n    if (upperCase) {\n      return out.toUpperCase()\n    } else {\n      return out\n    }\n  })\n}\n\n/**\n * Creates a function that transforms snake case strings to camel case.\n */\nexport function createCamelCaseMapper({\n  upperCase = false,\n} = {}): StringMapper {\n  return memoize((str: string): string => {\n    if (str.length === 0) {\n      return str\n    }\n\n    if (upperCase && isAllUpperCaseSnakeCase(str)) {\n      // Only convert to lower case if the string is all upper\n      // case snake_case. This allows camelCase strings to go\n      // through without changing.\n      str = str.toLowerCase()\n    }\n\n    let out = str[0]\n\n    for (let i = 1, l = str.length; i < l; ++i) {\n      const char = str[i]\n      const prevChar = str[i - 1]\n\n      if (char !== '_') {\n        if (prevChar === '_') {\n          out += char.toUpperCase()\n        } else {\n          out += char\n        }\n      }\n    }\n\n    return out\n  })\n}\n\nfunction isAllUpperCaseSnakeCase(str: string): boolean {\n  for (let i = 1, l = str.length; i < l; ++i) {\n    const char = str[i]\n\n    if (char !== '_' && char !== char.toUpperCase()) {\n      return false\n    }\n  }\n\n  return true\n}\n\nfunction isDigit(char: string): boolean {\n  return char >= '0' && char <= '9'\n}\n\nfunction memoize(func: StringMapper): StringMapper {\n  const cache = new Map<string, string>()\n\n  return (str: string) => {\n    let mapped = cache.get(str)\n\n    if (!mapped) {\n      mapped = func(str)\n      cache.set(str, mapped)\n    }\n\n    return mapped\n  }\n}\n"
  },
  {
    "path": "src/plugin/deduplicate-joins/deduplicate-joins-plugin.ts",
    "content": "import type { QueryResult } from '../../driver/database-connection.js'\nimport type { RootOperationNode } from '../../query-compiler/query-compiler.js'\nimport type { UnknownRow } from '../../util/type-utils.js'\nimport type {\n  KyselyPlugin,\n  PluginTransformQueryArgs,\n  PluginTransformResultArgs,\n} from '../kysely-plugin.js'\nimport { DeduplicateJoinsTransformer } from './deduplicate-joins-transformer.js'\n\n/**\n * Plugin that removes duplicate joins from queries.\n *\n * See [this recipe](https://github.com/kysely-org/kysely/blob/master/site/docs/recipes/0008-deduplicate-joins.md)\n */\nexport class DeduplicateJoinsPlugin implements KyselyPlugin {\n  readonly #transformer = new DeduplicateJoinsTransformer()\n\n  transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n    return this.#transformer.transformNode(args.node, args.queryId)\n  }\n\n  transformResult(\n    args: PluginTransformResultArgs,\n  ): Promise<QueryResult<UnknownRow>> {\n    return Promise.resolve(args.result)\n  }\n}\n"
  },
  {
    "path": "src/plugin/deduplicate-joins/deduplicate-joins-transformer.ts",
    "content": "import type { DeleteQueryNode } from '../../operation-node/delete-query-node.js'\nimport type { JoinNode } from '../../operation-node/join-node.js'\nimport { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js'\nimport type { SelectQueryNode } from '../../operation-node/select-query-node.js'\nimport type { UpdateQueryNode } from '../../operation-node/update-query-node.js'\nimport { compare, freeze } from '../../util/object-utils.js'\nimport type { QueryId } from '../../util/query-id.js'\n\nexport class DeduplicateJoinsTransformer extends OperationNodeTransformer {\n  protected transformSelectQuery(\n    node: SelectQueryNode,\n    queryId: QueryId,\n  ): SelectQueryNode {\n    return this.#transformQuery(super.transformSelectQuery(node, queryId))\n  }\n\n  protected transformUpdateQuery(\n    node: UpdateQueryNode,\n    queryId: QueryId,\n  ): UpdateQueryNode {\n    return this.#transformQuery(super.transformUpdateQuery(node, queryId))\n  }\n\n  protected transformDeleteQuery(\n    node: DeleteQueryNode,\n    queryId: QueryId,\n  ): DeleteQueryNode {\n    return this.#transformQuery(super.transformDeleteQuery(node, queryId))\n  }\n\n  #transformQuery<\n    T extends SelectQueryNode | UpdateQueryNode | DeleteQueryNode,\n  >(node: T): T {\n    if (!node.joins || node.joins.length === 0) {\n      return node\n    }\n\n    return freeze({\n      ...node,\n      joins: this.#deduplicateJoins(node.joins),\n    })\n  }\n\n  #deduplicateJoins(joins: ReadonlyArray<JoinNode>): ReadonlyArray<JoinNode> {\n    const out: JoinNode[] = []\n\n    for (let i = 0; i < joins.length; ++i) {\n      let foundDuplicate = false\n\n      for (let j = 0; j < out.length; ++j) {\n        if (compare(joins[i], out[j])) {\n          foundDuplicate = true\n          break\n        }\n      }\n\n      if (!foundDuplicate) {\n        out.push(joins[i])\n      }\n    }\n\n    return freeze(out)\n  }\n}\n"
  },
  {
    "path": "src/plugin/handle-empty-in-lists/handle-empty-in-lists-plugin.ts",
    "content": "import type { QueryResult } from '../../driver/database-connection.js'\nimport type { RootOperationNode } from '../../query-compiler/query-compiler.js'\nimport type {\n  KyselyPlugin,\n  PluginTransformQueryArgs,\n  PluginTransformResultArgs,\n} from '../kysely-plugin.js'\nimport type { UnknownRow } from '../../util/type-utils.js'\nimport { HandleEmptyInListsTransformer } from './handle-empty-in-lists-transformer.js'\nimport type { HandleEmptyInListsOptions } from './handle-empty-in-lists.js'\n\n/**\n * A plugin that allows handling `in ()` and `not in ()` expressions.\n *\n * These expressions are invalid SQL syntax for many databases, and result in runtime\n * database errors.\n *\n * The workarounds used by other libraries always involve modifying the query under\n * the hood, which is not aligned with Kysely's philosophy of WYSIWYG. We recommend manually checking\n * for empty arrays before passing them as arguments to `in` and `not in` expressions\n * instead, but understand that this can be cumbersome. Hence we're going with an\n * opt-in approach where you can choose if and how to handle these cases. We do\n * not want to make this the default behavior, as it can lead to unexpected behavior.\n * Use it at your own risk. Test it. Make sure it works as expected for you.\n *\n * Using this plugin also allows you to throw an error (thus avoiding unnecessary\n * requests to the database) or print a warning in these cases.\n *\n * ### Examples\n *\n * The following strategy replaces the `in`/`not in` expression with a noncontingent\n * expression. A contradiction (falsy) `1 = 0` for `in`, and a tautology (truthy) `1 = 1` for `not in`),\n * similarily to how {@link https://github.com/knex/knex/blob/176151d8048b2a7feeb89a3d649a5580786d4f4e/docs/src/guide/query-builder.md#L1763 | Knex.js},\n * {@link https://github.com/prisma/prisma-engines/blob/99168c54187178484dae45d9478aa40cfd1866d2/quaint/src/visitor.rs#L804-L823 | PrismaORM},\n * {@link https://github.com/laravel/framework/blob/8.x/src/Illuminate/Database/Query/Grammars/Grammar.php#L284-L291 | Laravel},\n * {@link https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine.params.empty_in_strategy | SQLAlchemy}\n * handle this.\n *\n * ```ts\n * import Sqlite from 'better-sqlite3'\n * import {\n *   HandleEmptyInListsPlugin,\n *   Kysely,\n *   replaceWithNoncontingentExpression,\n *   SqliteDialect,\n * } from 'kysely'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new SqliteDialect({\n *     database: new Sqlite(':memory:'),\n *   }),\n *   plugins: [\n *     new HandleEmptyInListsPlugin({\n *       strategy: replaceWithNoncontingentExpression\n *     })\n *   ],\n * })\n *\n * const results = await db\n *   .selectFrom('person')\n *   .where('id', 'in', [])\n *   .where('first_name', 'not in', [])\n *   .selectAll()\n *   .execute()\n * ```\n *\n * The generated SQL (SQLite):\n *\n * ```sql\n * select * from \"person\" where 1 = 0 and 1 = 1\n * ```\n *\n * The following strategy does the following:\n *\n * When `in`, pushes a `null` value into the empty list resulting in `in (null)`,\n * similiarly to how {@link https://github.com/typeorm/typeorm/blob/0280cdc451c35ef73c830eb1191c95d34f6ce06e/src/query-builder/QueryBuilder.ts#L919-L922 | TypeORM}\n * and {@link https://github.com/sequelize/sequelize/blob/0f2891c6897e12bf9bf56df344aae5b698f58c7d/packages/core/src/abstract-dialect/where-sql-builder.ts#L368-L379 | Sequelize}\n * handle `in ()`. `in (null)` is logically the equivalent of `= null`, which returns\n * `null`, which is a falsy expression in most SQL databases. We recommend NOT\n * using this strategy if you plan to use `in` in `select`, `returning`, or `output`\n * clauses, as the return type differs from the `SqlBool` default type for comparisons.\n *\n * When `not in`, casts the left operand as `char` and pushes a unique value into\n * the empty list resulting in `cast({{lhs}} as char) not in ({{VALUE}})`. Casting\n * is required to avoid database errors with non-string values.\n *\n * ```ts\n * import Sqlite from 'better-sqlite3'\n * import {\n *   HandleEmptyInListsPlugin,\n *   Kysely,\n *   pushValueIntoList,\n *   SqliteDialect\n * } from 'kysely'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new SqliteDialect({\n *     database: new Sqlite(':memory:'),\n *   }),\n *   plugins: [\n *     new HandleEmptyInListsPlugin({\n *       strategy: pushValueIntoList('__kysely_no_values_were_provided__') // choose a unique value for not in. has to be something with zero chance being in the data.\n *     })\n *   ],\n * })\n *\n * const results = await db\n *   .selectFrom('person')\n *   .where('id', 'in', [])\n *   .where('first_name', 'not in', [])\n *   .selectAll()\n *   .execute()\n * ```\n *\n * The generated SQL (SQLite):\n *\n * ```sql\n * select * from \"person\" where \"id\" in (null) and cast(\"first_name\" as char) not in ('__kysely_no_values_were_provided__')\n * ```\n *\n * The following custom strategy throws an error when an empty list is encountered\n * to avoid unnecessary requests to the database:\n *\n * ```ts\n * import Sqlite from 'better-sqlite3'\n * import {\n *   HandleEmptyInListsPlugin,\n *   Kysely,\n *   SqliteDialect\n * } from 'kysely'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new SqliteDialect({\n *     database: new Sqlite(':memory:'),\n *   }),\n *   plugins: [\n *     new HandleEmptyInListsPlugin({\n *       strategy: () => {\n *         throw new Error('Empty in/not-in is not allowed')\n *       }\n *     })\n *   ],\n * })\n *\n * const results = await db\n *   .selectFrom('person')\n *   .where('id', 'in', [])\n *   .selectAll()\n *   .execute() // throws an error with 'Empty in/not-in is not allowed' message!\n * ```\n */\nexport class HandleEmptyInListsPlugin implements KyselyPlugin {\n  readonly #transformer: HandleEmptyInListsTransformer\n\n  constructor(readonly opt: HandleEmptyInListsOptions) {\n    this.#transformer = new HandleEmptyInListsTransformer(opt.strategy)\n  }\n\n  transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n    return this.#transformer.transformNode(args.node, args.queryId)\n  }\n\n  async transformResult(\n    args: PluginTransformResultArgs,\n  ): Promise<QueryResult<UnknownRow>> {\n    return args.result\n  }\n}\n"
  },
  {
    "path": "src/plugin/handle-empty-in-lists/handle-empty-in-lists-transformer.ts",
    "content": "import type { BinaryOperationNode } from '../../operation-node/binary-operation-node.js'\nimport { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js'\nimport { PrimitiveValueListNode } from '../../operation-node/primitive-value-list-node.js'\nimport { OperatorNode } from '../../operation-node/operator-node.js'\nimport type {\n  EmptyInListNode,\n  EmptyInListsStrategy,\n} from './handle-empty-in-lists.js'\nimport { ValueListNode } from '../../operation-node/value-list-node.js'\n\nexport class HandleEmptyInListsTransformer extends OperationNodeTransformer {\n  readonly #strategy: EmptyInListsStrategy\n\n  constructor(strategy: EmptyInListsStrategy) {\n    super()\n    this.#strategy = strategy\n  }\n\n  protected transformBinaryOperation(\n    node: BinaryOperationNode,\n  ): BinaryOperationNode {\n    if (this.#isEmptyInListNode(node)) {\n      return this.#strategy(node)\n    }\n\n    return node\n  }\n\n  #isEmptyInListNode(node: BinaryOperationNode): node is EmptyInListNode {\n    const { operator, rightOperand } = node\n\n    return (\n      (PrimitiveValueListNode.is(rightOperand) ||\n        ValueListNode.is(rightOperand)) &&\n      rightOperand.values.length === 0 &&\n      OperatorNode.is(operator) &&\n      (operator.operator === 'in' || operator.operator === 'not in')\n    )\n  }\n}\n"
  },
  {
    "path": "src/plugin/handle-empty-in-lists/handle-empty-in-lists.ts",
    "content": "import { BinaryOperationNode } from '../../operation-node/binary-operation-node.js'\nimport { CastNode } from '../../operation-node/cast-node.js'\nimport { DataTypeNode } from '../../operation-node/data-type-node.js'\nimport { OperatorNode } from '../../operation-node/operator-node.js'\nimport type { ParensNode } from '../../operation-node/parens-node.js'\nimport type { PrimitiveValueListNode } from '../../operation-node/primitive-value-list-node.js'\nimport { ValueListNode } from '../../operation-node/value-list-node.js'\nimport { ValueNode } from '../../operation-node/value-node.js'\nimport { freeze } from '../../util/object-utils.js'\n\nexport interface HandleEmptyInListsOptions {\n  /**\n   * The strategy to use when handling `in ()` and `not in ()`.\n   *\n   * See {@link HandleEmptyInListsPlugin} for examples.\n   */\n  strategy: EmptyInListsStrategy\n}\n\nexport type EmptyInListNode = BinaryOperationNode & {\n  operator: OperatorNode & {\n    operator: 'in' | 'not in'\n  }\n  rightOperand: (ValueListNode | PrimitiveValueListNode) & {\n    values: Readonly<[]>\n  }\n}\n\nexport type EmptyInListsStrategy = (\n  node: EmptyInListNode,\n) => BinaryOperationNode\n\nlet contradiction: BinaryOperationNode\nlet eq: OperatorNode\nlet one: ValueNode\nlet tautology: BinaryOperationNode\n/**\n * Replaces the `in`/`not in` expression with a noncontingent expression (always true or always\n * false) depending on the original operator.\n *\n * This is how Knex.js, PrismaORM, Laravel, and SQLAlchemy handle `in ()` and `not in ()`.\n *\n * See {@link pushValueIntoList} for an alternative strategy.\n */\nexport function replaceWithNoncontingentExpression(\n  node: EmptyInListNode,\n): BinaryOperationNode {\n  const _one = (one ||= ValueNode.createImmediate(1))\n  const _eq = (eq ||= OperatorNode.create('='))\n\n  if (node.operator.operator === 'in') {\n    return (contradiction ||= BinaryOperationNode.create(\n      _one,\n      _eq,\n      ValueNode.createImmediate(0),\n    ))\n  }\n\n  return (tautology ||= BinaryOperationNode.create(_one, _eq, _one))\n}\n\nlet char: DataTypeNode\nlet listNull: ValueListNode\nlet listVal: ValueListNode\n/**\n * When `in`, pushes a `null` value into the list resulting in `in (null)`. This\n * is how TypeORM and Sequelize handle `in ()`. `in (null)` is logically the equivalent\n * of `= null`, which returns `null`, which is a falsy expression in most SQL databases.\n * We recommend NOT using this strategy if you plan to use `in` in `select`, `returning`,\n * or `output` clauses, as the return type differs from the `SqlBool` default type.\n *\n * When `not in`, casts the left operand as `char` and pushes a literal value into\n * the list resulting in `cast({{lhs}} as char) not in ({{VALUE}})`. Casting\n * is required to avoid database errors with non-string columns.\n *\n * See {@link replaceWithNoncontingentExpression} for an alternative strategy.\n */\nexport function pushValueIntoList(\n  uniqueNotInLiteral: '__kysely_no_values_were_provided__' | (string & {}),\n): EmptyInListsStrategy {\n  return function pushValueIntoList(node) {\n    if (node.operator.operator === 'in') {\n      return freeze({\n        ...node,\n        rightOperand: (listNull ||= ValueListNode.create([\n          ValueNode.createImmediate(null),\n        ])),\n      })\n    }\n\n    return freeze({\n      ...node,\n      leftOperand: CastNode.create(\n        node.leftOperand,\n        (char ||= DataTypeNode.create('char')),\n      ),\n      rightOperand: (listVal ||= ValueListNode.create([\n        ValueNode.createImmediate(uniqueNotInLiteral),\n      ])),\n    })\n  }\n}\n"
  },
  {
    "path": "src/plugin/immediate-value/immediate-value-plugin.ts",
    "content": "import type { QueryResult } from '../../driver/database-connection.js'\nimport type { RootOperationNode } from '../../query-compiler/query-compiler.js'\nimport type { UnknownRow } from '../../util/type-utils.js'\nimport type {\n  KyselyPlugin,\n  PluginTransformQueryArgs,\n  PluginTransformResultArgs,\n} from '../kysely-plugin.js'\nimport { ImmediateValueTransformer } from './immediate-value-transformer.js'\n\n/**\n * Transforms all ValueNodes to immediate.\n *\n * WARNING! This should never be part of the public API. Users should never use this.\n * This is an internal helper.\n *\n * @internal\n */\nexport class ImmediateValuePlugin implements KyselyPlugin {\n  readonly #transformer = new ImmediateValueTransformer()\n\n  transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n    return this.#transformer.transformNode(args.node, args.queryId)\n  }\n\n  transformResult(\n    args: PluginTransformResultArgs,\n  ): Promise<QueryResult<UnknownRow>> {\n    return Promise.resolve(args.result)\n  }\n}\n"
  },
  {
    "path": "src/plugin/immediate-value/immediate-value-transformer.ts",
    "content": "import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js'\nimport type { PrimitiveValueListNode } from '../../operation-node/primitive-value-list-node.js'\nimport { ValueListNode } from '../../operation-node/value-list-node.js'\nimport { ValueNode } from '../../operation-node/value-node.js'\n\n/**\n * Transforms all ValueNodes to immediate.\n *\n * WARNING! This should never be part of the public API. Users should never use this.\n * This is an internal helper.\n *\n * @internal\n */\nexport class ImmediateValueTransformer extends OperationNodeTransformer {\n  override transformPrimitiveValueList(\n    node: PrimitiveValueListNode,\n  ): PrimitiveValueListNode {\n    return ValueListNode.create(\n      node.values.map(ValueNode.createImmediate),\n    ) as any\n  }\n\n  override transformValue(node: ValueNode): ValueNode {\n    return ValueNode.createImmediate(node.value)\n  }\n}\n"
  },
  {
    "path": "src/plugin/kysely-plugin.ts",
    "content": "import type { QueryResult } from '../driver/database-connection.js'\nimport type { RootOperationNode } from '../query-compiler/query-compiler.js'\nimport type { QueryId } from '../util/query-id.js'\nimport type { UnknownRow } from '../util/type-utils.js'\n\nexport interface KyselyPlugin {\n  /**\n   * This is called for each query before it is executed. You can modify the query by\n   * transforming its {@link OperationNode} tree provided in {@link PluginTransformQueryArgs.node | args.node}\n   * and returning the transformed tree. You'd usually want to use an {@link OperationNodeTransformer}\n   * for this.\n   *\n   * If you need to pass some query-related data between this method and `transformResult` you\n   * can use a `WeakMap` with {@link PluginTransformQueryArgs.queryId | args.queryId} as the key:\n   *\n   * ```ts\n   * import type {\n   *   KyselyPlugin,\n   *   QueryResult,\n   *   RootOperationNode,\n   *   UnknownRow\n   * } from 'kysely'\n   *\n   * interface MyData {\n   *   // ...\n   * }\n   * const data = new WeakMap<any, MyData>()\n   *\n   * const plugin = {\n   *   transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n   *     const something: MyData = {}\n   *\n   *     // ...\n   *\n   *     data.set(args.queryId, something)\n   *\n   *     // ...\n   *\n   *     return args.node\n   *   },\n   *\n   *   async transformResult(args: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>> {\n   *     // ...\n   *\n   *     const something = data.get(args.queryId)\n   *\n   *     // ...\n   *\n   *     return args.result\n   *   }\n   * } satisfies KyselyPlugin\n   * ```\n   *\n   * You should use a `WeakMap` instead of a `Map` or some other strong references because `transformQuery`\n   * is not always matched by a call to `transformResult` which would leave orphaned items in the map\n   * and cause a memory leak.\n   */\n  transformQuery(args: PluginTransformQueryArgs): RootOperationNode\n\n  /**\n   * This method is called for each query after it has been executed. The result\n   * of the query can be accessed through {@link PluginTransformResultArgs.result | args.result}.\n   * You can modify the result and return the modifier result.\n   */\n  transformResult(\n    args: PluginTransformResultArgs,\n  ): Promise<QueryResult<UnknownRow>>\n}\n\nexport interface PluginTransformQueryArgs {\n  readonly queryId: QueryId\n  readonly node: RootOperationNode\n}\n\nexport interface PluginTransformResultArgs {\n  readonly queryId: QueryId\n  readonly result: QueryResult<UnknownRow>\n}\n"
  },
  {
    "path": "src/plugin/noop-plugin.ts",
    "content": "import type { QueryResult } from '../driver/database-connection.js'\nimport type { RootOperationNode } from '../query-compiler/query-compiler.js'\nimport type { UnknownRow } from '../util/type-utils.js'\nimport type {\n  KyselyPlugin,\n  PluginTransformQueryArgs,\n  PluginTransformResultArgs,\n} from './kysely-plugin.js'\n\nexport class NoopPlugin implements KyselyPlugin {\n  transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n    return args.node\n  }\n\n  async transformResult(\n    args: PluginTransformResultArgs,\n  ): Promise<QueryResult<UnknownRow>> {\n    return args.result\n  }\n}\n"
  },
  {
    "path": "src/plugin/parse-json-results/parse-json-results-plugin.ts",
    "content": "import type { QueryResult } from '../../driver/database-connection.js'\nimport type { RootOperationNode } from '../../query-compiler/query-compiler.js'\nimport { isPlainObject, isString } from '../../util/object-utils.js'\nimport type { UnknownRow } from '../../util/type-utils.js'\nimport type {\n  KyselyPlugin,\n  PluginTransformQueryArgs,\n  PluginTransformResultArgs,\n} from '../kysely-plugin.js'\n\nexport interface ParseJSONResultsPluginOptions {\n  /**\n   * When `'in-place'`, arrays' and objects' values are parsed in-place. This is\n   * the most time and space efficient option.\n   *\n   * This can result in runtime errors if some objects/arrays are readonly.\n   *\n   * When `'create'`, new arrays and objects are created to avoid such errors.\n   *\n   * Defaults to `'in-place'`.\n   */\n  objectStrategy?: ObjectStrategy\n}\n\ntype ObjectStrategy = 'in-place' | 'create'\n\n/**\n * Parses JSON strings in query results into JSON objects.\n *\n * This plugin can be useful with dialects that don't automatically parse\n * JSON into objects and arrays but return JSON strings instead.\n *\n * To apply this plugin globally, pass an instance of it to the `plugins` option\n * when creating a new `Kysely` instance:\n *\n * ```ts\n * import * as Sqlite from 'better-sqlite3'\n * import { Kysely, ParseJSONResultsPlugin, SqliteDialect } from 'kysely'\n * import type { Database } from 'type-editor' // imaginary module\n *\n * const db = new Kysely<Database>({\n *   dialect: new SqliteDialect({\n *     database: new Sqlite(':memory:'),\n *   }),\n *   plugins: [new ParseJSONResultsPlugin()],\n * })\n * ```\n *\n * To apply this plugin to a single query:\n *\n * ```ts\n * import { ParseJSONResultsPlugin } from 'kysely'\n * import { jsonArrayFrom } from 'kysely/helpers/sqlite'\n *\n * const result = await db\n *   .selectFrom('person')\n *   .select((eb) => [\n *     'id',\n *     'first_name',\n *     'last_name',\n *     jsonArrayFrom(\n *       eb.selectFrom('pet')\n *         .whereRef('owner_id', '=', 'person.id')\n *         .select(['name', 'species'])\n *     ).as('pets')\n *   ])\n *   .withPlugin(new ParseJSONResultsPlugin())\n *   .execute()\n * ```\n */\nexport class ParseJSONResultsPlugin implements KyselyPlugin {\n  readonly #objectStrategy: ObjectStrategy\n\n  constructor(readonly opt: ParseJSONResultsPluginOptions = {}) {\n    this.#objectStrategy = opt.objectStrategy || 'in-place'\n  }\n\n  // noop\n  transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n    return args.node\n  }\n\n  async transformResult(\n    args: PluginTransformResultArgs,\n  ): Promise<QueryResult<UnknownRow>> {\n    return {\n      ...args.result,\n      rows: parseArray(args.result.rows, this.#objectStrategy),\n    }\n  }\n}\n\nfunction parseArray<T>(arr: T[], objectStrategy: ObjectStrategy): T[] {\n  const target = objectStrategy === 'create' ? new Array(arr.length) : arr\n\n  for (let i = 0; i < arr.length; ++i) {\n    target[i] = parse(arr[i], objectStrategy) as T\n  }\n\n  return target\n}\n\nfunction parse(obj: unknown, objectStrategy: ObjectStrategy): unknown {\n  if (isString(obj)) {\n    return parseString(obj)\n  }\n\n  if (Array.isArray(obj)) {\n    return parseArray(obj, objectStrategy)\n  }\n\n  if (isPlainObject(obj)) {\n    return parseObject(obj, objectStrategy)\n  }\n\n  return obj\n}\n\nfunction parseString(str: string): unknown {\n  if (maybeJson(str)) {\n    try {\n      return parse(JSON.parse(str), 'in-place')\n    } catch (err) {\n      // this catch block is intentionally empty.\n    }\n  }\n\n  return str\n}\n\nfunction maybeJson(value: string): boolean {\n  return value.match(/^[\\[\\{]/) != null\n}\n\nfunction parseObject(\n  obj: Record<string, unknown>,\n  objectStrategy: ObjectStrategy,\n): Record<string, unknown> {\n  const target = objectStrategy === 'create' ? {} : obj\n\n  for (const key in obj) {\n    target[key] = parse(obj[key], objectStrategy)\n  }\n\n  return target\n}\n"
  },
  {
    "path": "src/plugin/with-schema/with-schema-plugin.ts",
    "content": "import type { QueryResult } from '../../driver/database-connection.js'\nimport type { RootOperationNode } from '../../query-compiler/query-compiler.js'\nimport { WithSchemaTransformer } from './with-schema-transformer.js'\nimport type {\n  KyselyPlugin,\n  PluginTransformQueryArgs,\n  PluginTransformResultArgs,\n} from '../kysely-plugin.js'\nimport type { UnknownRow } from '../../util/type-utils.js'\n\nexport class WithSchemaPlugin implements KyselyPlugin {\n  readonly #transformer: WithSchemaTransformer\n\n  constructor(schema: string) {\n    this.#transformer = new WithSchemaTransformer(schema)\n  }\n\n  transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n    return this.#transformer.transformNode(args.node, args.queryId)\n  }\n\n  async transformResult(\n    args: PluginTransformResultArgs,\n  ): Promise<QueryResult<UnknownRow>> {\n    return args.result\n  }\n}\n"
  },
  {
    "path": "src/plugin/with-schema/with-schema-transformer.ts",
    "content": "import type { AggregateFunctionNode } from '../../operation-node/aggregate-function-node.js'\nimport { AliasNode } from '../../operation-node/alias-node.js'\nimport type { FunctionNode } from '../../operation-node/function-node.js'\nimport { IdentifierNode } from '../../operation-node/identifier-node.js'\nimport { JoinNode } from '../../operation-node/join-node.js'\nimport { ListNode } from '../../operation-node/list-node.js'\nimport { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js'\nimport type { OperationNode } from '../../operation-node/operation-node.js'\nimport type { ReferencesNode } from '../../operation-node/references-node.js'\nimport { SchemableIdentifierNode } from '../../operation-node/schemable-identifier-node.js'\nimport type { SelectModifierNode } from '../../operation-node/select-modifier-node.js'\nimport { TableNode } from '../../operation-node/table-node.js'\nimport { UsingNode } from '../../operation-node/using-node.js'\nimport type { WithNode } from '../../operation-node/with-node.js'\nimport type { RootOperationNode } from '../../query-compiler/query-compiler.js'\nimport { freeze } from '../../util/object-utils.js'\nimport type { QueryId } from '../../util/query-id.js'\n\n// This object exist only so that we get a type error when a new RootOperationNode\n// is added. If you get a type error here, make sure to add the new root node and\n// handle it correctly in the transformer.\n//\n// DO NOT REFACTOR THIS EVEN IF IT SEEMS USELESS TO YOU!\nconst ROOT_OPERATION_NODES: Record<RootOperationNode['kind'], true> = freeze({\n  AlterTableNode: true,\n  CreateIndexNode: true,\n  CreateSchemaNode: true,\n  CreateTableNode: true,\n  CreateTypeNode: true,\n  CreateViewNode: true,\n  RefreshMaterializedViewNode: true,\n  DeleteQueryNode: true,\n  DropIndexNode: true,\n  DropSchemaNode: true,\n  DropTableNode: true,\n  DropTypeNode: true,\n  DropViewNode: true,\n  InsertQueryNode: true,\n  RawNode: true,\n  SelectQueryNode: true,\n  UpdateQueryNode: true,\n  MergeQueryNode: true,\n})\n\nconst SCHEMALESS_FUNCTIONS: Record<string, true> = {\n  json_agg: true,\n  to_json: true,\n}\n\nexport class WithSchemaTransformer extends OperationNodeTransformer {\n  readonly #schema: string\n  readonly #schemableIds = new Set<string>()\n  readonly #ctes = new Set<string>()\n\n  constructor(schema: string) {\n    super()\n    this.#schema = schema\n  }\n\n  protected override transformNodeImpl<T extends OperationNode>(\n    node: T,\n    queryId: QueryId,\n  ): T {\n    if (!this.#isRootOperationNode(node)) {\n      return super.transformNodeImpl(node, queryId)\n    }\n\n    const ctes = this.#collectCTEs(node)\n\n    for (const cte of ctes) {\n      this.#ctes.add(cte)\n    }\n\n    const tables = this.#collectSchemableIds(node)\n\n    for (const table of tables) {\n      this.#schemableIds.add(table)\n    }\n\n    const transformed = super.transformNodeImpl(node, queryId)\n\n    for (const table of tables) {\n      this.#schemableIds.delete(table)\n    }\n\n    for (const cte of ctes) {\n      this.#ctes.delete(cte)\n    }\n\n    return transformed\n  }\n\n  protected override transformSchemableIdentifier(\n    node: SchemableIdentifierNode,\n    queryId: QueryId,\n  ): SchemableIdentifierNode {\n    const transformed = super.transformSchemableIdentifier(node, queryId)\n\n    if (transformed.schema || !this.#schemableIds.has(node.identifier.name)) {\n      return transformed\n    }\n\n    return {\n      ...transformed,\n      schema: IdentifierNode.create(this.#schema),\n    }\n  }\n\n  protected override transformReferences(\n    node: ReferencesNode,\n    queryId: QueryId,\n  ): ReferencesNode {\n    const transformed = super.transformReferences(node, queryId)\n\n    if (transformed.table.table.schema) {\n      return transformed\n    }\n\n    return {\n      ...transformed,\n      table: TableNode.createWithSchema(\n        this.#schema,\n        transformed.table.table.identifier.name,\n      ),\n    }\n  }\n\n  protected override transformAggregateFunction(\n    node: AggregateFunctionNode,\n    queryId: QueryId,\n  ): AggregateFunctionNode {\n    return {\n      ...super.transformAggregateFunction({ ...node, aggregated: [] }, queryId),\n      aggregated: this.#transformTableArgsWithoutSchemas(\n        node,\n        queryId,\n        'aggregated',\n      ),\n    }\n  }\n\n  protected override transformFunction(\n    node: FunctionNode,\n    queryId: QueryId,\n  ): FunctionNode {\n    return {\n      ...super.transformFunction({ ...node, arguments: [] }, queryId),\n      arguments: this.#transformTableArgsWithoutSchemas(\n        node,\n        queryId,\n        'arguments',\n      ),\n    }\n  }\n\n  protected override transformSelectModifier(\n    node: SelectModifierNode,\n    queryId: QueryId,\n  ): SelectModifierNode {\n    return {\n      ...super.transformSelectModifier({ ...node, of: undefined }, queryId),\n      of: node.of?.map((item) =>\n        TableNode.is(item) && !item.table.schema\n          ? {\n              ...item,\n              table: this.transformIdentifier(item.table.identifier, queryId),\n            }\n          : this.transformNode(item, queryId),\n      ),\n    }\n  }\n\n  #transformTableArgsWithoutSchemas<\n    A extends string,\n    N extends { func: string } & {\n      [K in A]: readonly OperationNode[]\n    },\n  >(node: N, queryId: QueryId, argsKey: A): readonly OperationNode[] {\n    return SCHEMALESS_FUNCTIONS[node.func]\n      ? node[argsKey].map((arg) =>\n          !TableNode.is(arg) || arg.table.schema\n            ? this.transformNode(arg, queryId)\n            : {\n                ...arg,\n                table: this.transformIdentifier(arg.table.identifier, queryId),\n              },\n        )\n      : this.transformNodeList(node[argsKey], queryId)\n  }\n\n  #isRootOperationNode(node: OperationNode): node is RootOperationNode {\n    return node.kind in ROOT_OPERATION_NODES\n  }\n\n  #collectSchemableIds(node: RootOperationNode): Set<string> {\n    const schemableIds = new Set<string>()\n\n    if ('name' in node && node.name && SchemableIdentifierNode.is(node.name)) {\n      this.#collectSchemableId(node.name, schemableIds)\n    }\n\n    if ('from' in node && node.from) {\n      for (const from of node.from.froms) {\n        this.#collectSchemableIdsFromTableExpr(from, schemableIds)\n      }\n    }\n\n    if ('into' in node && node.into) {\n      this.#collectSchemableIdsFromTableExpr(node.into, schemableIds)\n    }\n\n    if ('table' in node && node.table) {\n      this.#collectSchemableIdsFromTableExpr(node.table, schemableIds)\n    }\n\n    if ('joins' in node && node.joins) {\n      for (const join of node.joins) {\n        this.#collectSchemableIdsFromTableExpr(join.table, schemableIds)\n      }\n    }\n\n    if ('using' in node && node.using) {\n      if (JoinNode.is(node.using)) {\n        this.#collectSchemableIdsFromTableExpr(node.using.table, schemableIds)\n      } else {\n        this.#collectSchemableIdsFromTableExpr(node.using, schemableIds)\n      }\n    }\n\n    return schemableIds\n  }\n\n  #collectCTEs(node: RootOperationNode): Set<string> {\n    const ctes = new Set<string>()\n\n    if ('with' in node && node.with) {\n      this.#collectCTEIds(node.with, ctes)\n    }\n\n    return ctes\n  }\n\n  #collectSchemableIdsFromTableExpr(\n    node: OperationNode,\n    schemableIds: Set<string>,\n  ): void {\n    if (TableNode.is(node)) {\n      return this.#collectSchemableId(node.table, schemableIds)\n    }\n\n    if (AliasNode.is(node) && TableNode.is(node.node)) {\n      return this.#collectSchemableId(node.node.table, schemableIds)\n    }\n\n    if (ListNode.is(node)) {\n      for (const table of node.items) {\n        this.#collectSchemableIdsFromTableExpr(table, schemableIds)\n      }\n      return\n    }\n\n    if (UsingNode.is(node)) {\n      for (const table of node.tables) {\n        this.#collectSchemableIdsFromTableExpr(table, schemableIds)\n      }\n      return\n    }\n  }\n\n  #collectSchemableId(\n    node: SchemableIdentifierNode,\n    schemableIds: Set<string>,\n  ): void {\n    const id = node.identifier.name\n\n    if (!this.#schemableIds.has(id) && !this.#ctes.has(id)) {\n      schemableIds.add(id)\n    }\n  }\n\n  #collectCTEIds(node: WithNode, ctes: Set<string>): void {\n    for (const expr of node.expressions) {\n      const cteId = expr.name.table.table.identifier.name\n\n      if (!this.#ctes.has(cteId)) {\n        ctes.add(cteId)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/query-builder/aggregate-function-builder.ts",
    "content": "import { freeze } from '../util/object-utils.js'\nimport { AggregateFunctionNode } from '../operation-node/aggregate-function-node.js'\nimport { AliasNode } from '../operation-node/alias-node.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport type { OverBuilder } from './over-builder.js'\nimport { createOverBuilder } from '../parser/parse-utils.js'\nimport type {\n  AliasableExpression,\n  AliasedExpression,\n  Expression,\n} from '../expression/expression.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport {\n  type ComparisonOperatorExpression,\n  type OperandValueExpressionOrList,\n  parseReferentialBinaryOperation,\n  parseValueBinaryOperationOrExpression,\n} from '../parser/binary-operation-parser.js'\nimport type { SqlBool } from '../util/type-utils.js'\nimport type { ExpressionOrFactory } from '../parser/expression-parser.js'\nimport {\n  type DirectedOrderByStringReference,\n  type OrderByExpression,\n  type OrderByModifiers,\n  parseOrderBy,\n} from '../parser/order-by-parser.js'\nimport type { OrderByInterface } from './order-by-interface.js'\nimport { QueryNode } from '../operation-node/query-node.js'\n\nexport class AggregateFunctionBuilder<DB, TB extends keyof DB, O = unknown>\n  implements OrderByInterface<DB, TB, {}>, AliasableExpression<O>\n{\n  readonly #props: AggregateFunctionBuilderProps\n\n  constructor(props: AggregateFunctionBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /** @private */\n  get expressionType(): O | undefined {\n    return undefined\n  }\n\n  /**\n   * Returns an aliased version of the function.\n   *\n   * In addition to slapping `as \"the_alias\"` to the end of the SQL,\n   * this method also provides strict typing:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select(\n   *     (eb) => eb.fn.count<number>('id').as('person_count')\n   *   )\n   *   .executeTakeFirstOrThrow()\n   *\n   * // `person_count: number` field exists in the result type.\n   * console.log(result.person_count)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select count(\"id\") as \"person_count\"\n   * from \"person\"\n   * ```\n   */\n  as<A extends string>(\n    alias: A,\n  ): AliasedAggregateFunctionBuilder<DB, TB, O, A> {\n    return new AliasedAggregateFunctionBuilder(this, alias)\n  }\n\n  /**\n   * Adds a `distinct` clause inside the function.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select((eb) =>\n   *     eb.fn.count<number>('first_name').distinct().as('first_name_count')\n   *   )\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select count(distinct \"first_name\") as \"first_name_count\"\n   * from \"person\"\n   * ```\n   */\n  distinct(): AggregateFunctionBuilder<DB, TB, O> {\n    return new AggregateFunctionBuilder({\n      ...this.#props,\n      aggregateFunctionNode: AggregateFunctionNode.cloneWithDistinct(\n        this.#props.aggregateFunctionNode,\n      ),\n    })\n  }\n\n  /**\n   * Adds an `order by` clause inside the aggregate function.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .select((eb) =>\n   *     eb.fn.jsonAgg('pet').orderBy('pet.name').as('person_pets')\n   *   )\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select json_agg(\"pet\" order by \"pet\".\"name\") as \"person_pets\"\n   * from \"person\"\n   * inner join \"pet\" ON \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ```\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers?: OrderByModifiers,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `orderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.\n   */\n  orderBy<\n    OE extends\n      | OrderByExpression<DB, TB, {}>\n      | DirectedOrderByStringReference<DB, TB, {}>,\n  >(exprs: ReadonlyArray<OE>): AggregateFunctionBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated It does ~2.9x more compile-time instantiations compared to a `orderBy(expr, direction)` call.\n   */\n  orderBy<OE extends DirectedOrderByStringReference<DB, TB, {}>>(\n    expr: OE,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated Use `orderBy(expr, (ob) => ...)` instead.\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers: Expression<any>,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  orderBy(...args: any[]): any {\n    return new AggregateFunctionBuilder({\n      ...this.#props,\n      aggregateFunctionNode: QueryNode.cloneWithOrderByItems(\n        this.#props.aggregateFunctionNode,\n        parseOrderBy(args),\n      ),\n    })\n  }\n\n  clearOrderBy(): AggregateFunctionBuilder<DB, TB, O> {\n    return new AggregateFunctionBuilder({\n      ...this.#props,\n      aggregateFunctionNode: QueryNode.cloneWithoutOrderBy(\n        this.#props.aggregateFunctionNode,\n      ),\n    })\n  }\n\n  /**\n   * Adds a `withing group` clause with a nested `order by` clause after the function.\n   *\n   * This is only supported by some dialects like PostgreSQL or MS SQL Server.\n   *\n   * ### Examples\n   *\n   * Most frequent person name:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select((eb) => [\n   *     eb.fn\n   *       .agg<string>('mode')\n   *       .withinGroupOrderBy('person.first_name')\n   *       .as('most_frequent_name')\n   *   ])\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select mode() within group (order by \"person\".\"first_name\") as \"most_frequent_name\"\n   * from \"person\"\n   * ```\n   */\n  withinGroupOrderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers?: OrderByModifiers,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `withinGroupOrderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.\n   */\n  withinGroupOrderBy<\n    OE extends\n      | OrderByExpression<DB, TB, {}>\n      | DirectedOrderByStringReference<DB, TB, {}>,\n  >(exprs: ReadonlyArray<OE>): AggregateFunctionBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated It does ~2.9x more compile-time instantiations compared to a `withinGroupOrderBy(expr, direction)` call.\n   */\n  withinGroupOrderBy<OE extends DirectedOrderByStringReference<DB, TB, {}>>(\n    expr: OE,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated Use `withinGroupOrderBy(expr, (ob) => ...)` instead.\n   */\n  withinGroupOrderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers: Expression<any>,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  withinGroupOrderBy(...args: any[]): any {\n    return new AggregateFunctionBuilder({\n      ...this.#props,\n      aggregateFunctionNode: AggregateFunctionNode.cloneWithOrderBy(\n        this.#props.aggregateFunctionNode,\n        parseOrderBy(args),\n        true,\n      ),\n    })\n  }\n\n  /**\n   * Adds a `filter` clause with a nested `where` clause after the function.\n   *\n   * Similar to {@link WhereInterface}'s `where` method.\n   *\n   * Also see {@link filterWhereRef}.\n   *\n   * ### Examples\n   *\n   * Count by gender:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select((eb) => [\n   *     eb.fn\n   *       .count<number>('id')\n   *       .filterWhere('gender', '=', 'female')\n   *       .as('female_count'),\n   *     eb.fn\n   *       .count<number>('id')\n   *       .filterWhere('gender', '=', 'male')\n   *       .as('male_count'),\n   *     eb.fn\n   *       .count<number>('id')\n   *       .filterWhere('gender', '=', 'other')\n   *       .as('other_count'),\n   *   ])\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   count(\"id\") filter(where \"gender\" = $1) as \"female_count\",\n   *   count(\"id\") filter(where \"gender\" = $2) as \"male_count\",\n   *   count(\"id\") filter(where \"gender\" = $3) as \"other_count\"\n   * from \"person\"\n   * ```\n   */\n  filterWhere<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  filterWhere<E extends ExpressionOrFactory<DB, TB, SqlBool>>(\n    expression: E,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  filterWhere(...args: any[]): any {\n    return new AggregateFunctionBuilder({\n      ...this.#props,\n      aggregateFunctionNode: AggregateFunctionNode.cloneWithFilter(\n        this.#props.aggregateFunctionNode,\n        parseValueBinaryOperationOrExpression(args),\n      ),\n    })\n  }\n\n  /**\n   * Adds a `filter` clause with a nested `where` clause after the function, where\n   * both sides of the operator are references to columns.\n   *\n   * Similar to {@link WhereInterface}'s `whereRef` method.\n   *\n   * ### Examples\n   *\n   * Count people with same first and last names versus general public:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select((eb) => [\n   *     eb.fn\n   *       .count<number>('id')\n   *       .filterWhereRef('first_name', '=', 'last_name')\n   *       .as('repeat_name_count'),\n   *     eb.fn.count<number>('id').as('total_count'),\n   *   ])\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   count(\"id\") filter(where \"first_name\" = \"last_name\") as \"repeat_name_count\",\n   *   count(\"id\") as \"total_count\"\n   * from \"person\"\n   * ```\n   */\n  filterWhereRef<\n    LRE extends ReferenceExpression<DB, TB>,\n    RRE extends ReferenceExpression<DB, TB>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): AggregateFunctionBuilder<DB, TB, O> {\n    return new AggregateFunctionBuilder({\n      ...this.#props,\n      aggregateFunctionNode: AggregateFunctionNode.cloneWithFilter(\n        this.#props.aggregateFunctionNode,\n        parseReferentialBinaryOperation(lhs, op, rhs),\n      ),\n    })\n  }\n\n  /**\n   * Adds an `over` clause (window functions) after the function.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select(\n   *     (eb) => eb.fn.avg<number>('age').over().as('average_age')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select avg(\"age\") over() as \"average_age\"\n   * from \"person\"\n   * ```\n   *\n   * Also supports passing a callback that returns an over builder,\n   * allowing to add partition by and sort by clauses inside over.\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select(\n   *     (eb) => eb.fn.avg<number>('age').over(\n   *       ob => ob.partitionBy('last_name').orderBy('first_name', 'asc')\n   *     ).as('average_age')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select avg(\"age\") over(partition by \"last_name\" order by \"first_name\" asc) as \"average_age\"\n   * from \"person\"\n   * ```\n   */\n  over(\n    over?: OverBuilderCallback<DB, TB>,\n  ): AggregateFunctionBuilder<DB, TB, O> {\n    const builder = createOverBuilder()\n\n    return new AggregateFunctionBuilder({\n      ...this.#props,\n      aggregateFunctionNode: AggregateFunctionNode.cloneWithOver(\n        this.#props.aggregateFunctionNode,\n        (over ? over(builder) : builder).toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  /**\n   * Casts the expression to the given type.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `AggregateFunctionBuilder` with a new output type.\n   */\n  $castTo<C>(): AggregateFunctionBuilder<DB, TB, C> {\n    return new AggregateFunctionBuilder(this.#props)\n  }\n\n  /**\n   * Omit null from the expression's type.\n   *\n   * This function can be useful in cases where you know an expression can't be\n   * null, but Kysely is unable to infer it.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of `this` with a new output type.\n   */\n  $notNull(): AggregateFunctionBuilder<DB, TB, Exclude<O, null>> {\n    return new AggregateFunctionBuilder(this.#props)\n  }\n\n  toOperationNode(): AggregateFunctionNode {\n    return this.#props.aggregateFunctionNode\n  }\n}\n\n/**\n * {@link AggregateFunctionBuilder} with an alias. The result of calling {@link AggregateFunctionBuilder.as}.\n */\nexport class AliasedAggregateFunctionBuilder<\n  DB,\n  TB extends keyof DB,\n  O = unknown,\n  A extends string = never,\n> implements AliasedExpression<O, A> {\n  readonly #aggregateFunctionBuilder: AggregateFunctionBuilder<DB, TB, O>\n  readonly #alias: A\n\n  constructor(\n    aggregateFunctionBuilder: AggregateFunctionBuilder<DB, TB, O>,\n    alias: A,\n  ) {\n    this.#aggregateFunctionBuilder = aggregateFunctionBuilder\n    this.#alias = alias\n  }\n\n  /** @private */\n  get expression(): Expression<O> {\n    return this.#aggregateFunctionBuilder\n  }\n\n  /** @private */\n  get alias(): A {\n    return this.#alias\n  }\n\n  toOperationNode(): AliasNode {\n    return AliasNode.create(\n      this.#aggregateFunctionBuilder.toOperationNode(),\n      IdentifierNode.create(this.#alias),\n    )\n  }\n}\n\nexport interface AggregateFunctionBuilderProps {\n  aggregateFunctionNode: AggregateFunctionNode\n}\n\nexport type OverBuilderCallback<DB, TB extends keyof DB> = (\n  builder: OverBuilder<DB, TB>,\n) => OverBuilder<any, any>\n"
  },
  {
    "path": "src/query-builder/case-builder.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport { ExpressionWrapper } from '../expression/expression-wrapper.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport { CaseNode } from '../operation-node/case-node.js'\nimport { WhenNode } from '../operation-node/when-node.js'\nimport {\n  type ComparisonOperatorExpression,\n  type OperandValueExpressionOrList,\n  parseValueBinaryOperationOrExpression,\n} from '../parser/binary-operation-parser.js'\nimport {\n  type ExtractTypeFromValueExpression,\n  isSafeImmediateValue,\n  parseSafeImmediateValue,\n  parseValueExpression,\n} from '../parser/value-parser.js'\nimport type { KyselyTypeError } from '../util/type-error.js'\n\nexport class CaseBuilder<\n  DB,\n  TB extends keyof DB,\n  W = unknown,\n  O = never,\n> implements Whenable<DB, TB, W, O> {\n  readonly #props: CaseBuilderProps\n\n  constructor(props: CaseBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  when<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: unknown extends W\n      ? RE\n      : KyselyTypeError<'when(lhs, op, rhs) is not supported when using case(value)'>,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): CaseThenBuilder<DB, TB, W, O>\n\n  when(expression: Expression<W>): CaseThenBuilder<DB, TB, W, O>\n\n  when(\n    value: unknown extends W\n      ? KyselyTypeError<'when(value) is only supported when using case(value)'>\n      : W,\n  ): CaseThenBuilder<DB, TB, W, O>\n\n  when(...args: any[]): any {\n    return new CaseThenBuilder({\n      ...this.#props,\n      node: CaseNode.cloneWithWhen(\n        this.#props.node,\n        WhenNode.create(parseValueBinaryOperationOrExpression(args)),\n      ),\n    })\n  }\n}\n\ninterface CaseBuilderProps {\n  readonly node: CaseNode\n}\n\nexport class CaseThenBuilder<DB, TB extends keyof DB, W, O> {\n  readonly #props: CaseBuilderProps\n\n  constructor(props: CaseBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Adds a `then` clause to the `case` statement.\n   *\n   * A `then` call can be followed by {@link Whenable.when}, {@link CaseWhenBuilder.else},\n   * {@link CaseWhenBuilder.end} or {@link CaseWhenBuilder.endCase} call.\n   *\n   * **Note:** Numbers, booleans, and `null` values are inlined directly into the\n   * SQL query string (e.g. `then 1`, `then true`, `then null`) instead of being\n   * added as parameterized values (e.g. `then $1`). This allows the database\n   * engine to correctly infer the data type of the `case` expression result.\n   * Without this behavior, all results would be returned as strings.\n   *\n   * String values are always parameterized as usual.\n   */\n  then<E extends Expression<unknown>>(\n    expression: E,\n  ): CaseWhenBuilder<DB, TB, W, O | ExtractTypeFromValueExpression<E>>\n\n  then<V>(value: V): CaseWhenBuilder<DB, TB, W, O | V>\n\n  then(valueExpression: any): any {\n    return new CaseWhenBuilder({\n      ...this.#props,\n      node: CaseNode.cloneWithThen(\n        this.#props.node,\n        isSafeImmediateValue(valueExpression)\n          ? parseSafeImmediateValue(valueExpression)\n          : parseValueExpression(valueExpression),\n      ),\n    })\n  }\n}\n\nexport class CaseWhenBuilder<DB, TB extends keyof DB, W, O>\n  implements Whenable<DB, TB, W, O>, Endable<DB, TB, O | null>\n{\n  readonly #props: CaseBuilderProps\n\n  constructor(props: CaseBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  when<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: unknown extends W\n      ? RE\n      : KyselyTypeError<'when(lhs, op, rhs) is not supported when using case(value)'>,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): CaseThenBuilder<DB, TB, W, O>\n\n  when(expression: Expression<W>): CaseThenBuilder<DB, TB, W, O>\n\n  when(\n    value: unknown extends W\n      ? KyselyTypeError<'when(value) is only supported when using case(value)'>\n      : W,\n  ): CaseThenBuilder<DB, TB, W, O>\n\n  when(...args: any[]): any {\n    return new CaseThenBuilder({\n      ...this.#props,\n      node: CaseNode.cloneWithWhen(\n        this.#props.node,\n        WhenNode.create(parseValueBinaryOperationOrExpression(args)),\n      ),\n    })\n  }\n\n  /**\n   * Adds an `else` clause to the `case` statement.\n   *\n   * An `else` call must be followed by an {@link Endable.end} or {@link Endable.endCase} call.\n   *\n   * **Note:** Numbers, booleans, and `null` values are inlined directly into the\n   * SQL query string (e.g. `else 0`, `else false`, `else null`) instead of being\n   * added as parameterized values (e.g. `else $1`). This allows the database\n   * engine to correctly infer the data type of the `case` expression result.\n   * Without this behavior, all results would be returned as strings.\n   *\n   * String values are always parameterized as usual.\n   */\n  else<E extends Expression<unknown>>(\n    expression: E,\n  ): CaseEndBuilder<DB, TB, O | ExtractTypeFromValueExpression<E>>\n\n  else<V>(value: V): CaseEndBuilder<DB, TB, O | V>\n\n  else(valueExpression: any): any {\n    return new CaseEndBuilder({\n      ...this.#props,\n      node: CaseNode.cloneWith(this.#props.node, {\n        else: isSafeImmediateValue(valueExpression)\n          ? parseSafeImmediateValue(valueExpression)\n          : parseValueExpression(valueExpression),\n      }),\n    })\n  }\n\n  end(): ExpressionWrapper<DB, TB, O | null> {\n    return new ExpressionWrapper(\n      CaseNode.cloneWith(this.#props.node, { isStatement: false }),\n    )\n  }\n\n  endCase(): ExpressionWrapper<DB, TB, O | null> {\n    return new ExpressionWrapper(\n      CaseNode.cloneWith(this.#props.node, { isStatement: true }),\n    )\n  }\n}\n\nexport class CaseEndBuilder<DB, TB extends keyof DB, O> implements Endable<\n  DB,\n  TB,\n  O\n> {\n  readonly #props: CaseBuilderProps\n\n  constructor(props: CaseBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  end(): ExpressionWrapper<DB, TB, O> {\n    return new ExpressionWrapper(\n      CaseNode.cloneWith(this.#props.node, { isStatement: false }),\n    )\n  }\n\n  endCase(): ExpressionWrapper<DB, TB, O> {\n    return new ExpressionWrapper(\n      CaseNode.cloneWith(this.#props.node, { isStatement: true }),\n    )\n  }\n}\n\ninterface Whenable<DB, TB extends keyof DB, W, O> {\n  /**\n   * Adds a `when` clause to the case statement.\n   *\n   * A `when` call must be followed by a {@link CaseThenBuilder.then} call.\n   */\n  when<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: unknown extends W\n      ? RE\n      : KyselyTypeError<'when(lhs, op, rhs) is not supported when using case(value)'>,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): CaseThenBuilder<DB, TB, W, O>\n\n  when(expression: Expression<W>): CaseThenBuilder<DB, TB, W, O>\n\n  when(\n    value: unknown extends W\n      ? KyselyTypeError<'when(value) is only supported when using case(value)'>\n      : W,\n  ): CaseThenBuilder<DB, TB, W, O>\n}\n\ninterface Endable<DB, TB extends keyof DB, O> {\n  /**\n   * Adds an `end` keyword to the case operator.\n   *\n   * `case` operators can only be used as part of a query.\n   * For a `case` statement used as part of a stored program, use {@link endCase} instead.\n   */\n  end(): ExpressionWrapper<DB, TB, O>\n\n  /**\n   * Adds `end case` keywords to the case statement.\n   *\n   * `case` statements can only be used for flow control in stored programs.\n   * For a `case` operator used as part of a query, use {@link end} instead.\n   */\n  endCase(): ExpressionWrapper<DB, TB, O>\n}\n"
  },
  {
    "path": "src/query-builder/cte-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { CommonTableExpressionNode } from '../operation-node/common-table-expression-node.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport class CTEBuilder<N extends string> implements OperationNodeSource {\n  readonly #props: CTEBuilderProps\n\n  constructor(props: CTEBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Makes the common table expression materialized.\n   */\n  materialized(): CTEBuilder<N> {\n    return new CTEBuilder({\n      ...this.#props,\n      node: CommonTableExpressionNode.cloneWith(this.#props.node, {\n        materialized: true,\n      }),\n    })\n  }\n\n  /**\n   * Makes the common table expression not materialized.\n   */\n  notMaterialized(): CTEBuilder<N> {\n    return new CTEBuilder({\n      ...this.#props,\n      node: CommonTableExpressionNode.cloneWith(this.#props.node, {\n        materialized: false,\n      }),\n    })\n  }\n\n  toOperationNode(): CommonTableExpressionNode {\n    return this.#props.node\n  }\n}\n\ninterface CTEBuilderProps {\n  readonly node: CommonTableExpressionNode\n}\n\nexport type CTEBuilderCallback<N extends string> = (\n  // N2 is needed for proper inference. Don't remove it.\n  cte: <N2 extends string>(name: N2) => CTEBuilder<N2>,\n) => CTEBuilder<N>\n"
  },
  {
    "path": "src/query-builder/delete-query-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport {\n  type JoinCallbackExpression,\n  type JoinReferenceExpression,\n  parseJoin,\n} from '../parser/join-parser.js'\nimport {\n  type From,\n  type FromTables,\n  parseTableExpressionOrList,\n  type TableExpression,\n  type TableExpressionOrList,\n} from '../parser/table-parser.js'\nimport {\n  parseSelectArg,\n  parseSelectAll,\n  type SelectExpression,\n  type SelectArg,\n  type SelectCallback,\n} from '../parser/select-parser.js'\nimport type {\n  ReturningAllRow,\n  ReturningCallbackRow,\n  ReturningRow,\n} from '../parser/returning-parser.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport { QueryNode } from '../operation-node/query-node.js'\nimport type {\n  DrainOuterGeneric,\n  NarrowPartial,\n  Nullable,\n  ShallowRecord,\n  SimplifyResult,\n  SimplifySingleResult,\n  SqlBool,\n} from '../util/type-utils.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport type { WhereInterface } from './where-interface.js'\nimport type { MultiTableReturningInterface } from './returning-interface.js'\nimport {\n  isNoResultErrorConstructor,\n  NoResultError,\n  type NoResultErrorConstructor,\n} from './no-result-error.js'\nimport { DeleteResult } from './delete-result.js'\nimport { DeleteQueryNode } from '../operation-node/delete-query-node.js'\nimport { LimitNode } from '../operation-node/limit-node.js'\nimport {\n  type OrderByExpression,\n  parseOrderBy,\n  type OrderByModifiers,\n  type DirectedOrderByStringReference,\n} from '../parser/order-by-parser.js'\nimport type { Explainable, ExplainFormat } from '../util/explainable.js'\nimport type { AliasedExpression, Expression } from '../expression/expression.js'\nimport {\n  type ComparisonOperatorExpression,\n  type OperandValueExpressionOrList,\n  parseValueBinaryOperationOrExpression,\n  parseReferentialBinaryOperation,\n} from '../parser/binary-operation-parser.js'\nimport type { KyselyTypeError } from '../util/type-error.js'\nimport type { Streamable } from '../util/streamable.js'\nimport type { ExpressionOrFactory } from '../parser/expression-parser.js'\nimport {\n  type ValueExpression,\n  parseValueExpression,\n} from '../parser/value-parser.js'\nimport { parseTop } from '../parser/top-parser.js'\nimport type {\n  OutputCallback,\n  OutputExpression,\n  OutputInterface,\n  SelectExpressionFromOutputCallback,\n  SelectExpressionFromOutputExpression,\n} from './output-interface.js'\nimport type { JoinType } from '../operation-node/join-node.js'\nimport type { OrderByInterface } from './order-by-interface.js'\n\nexport class DeleteQueryBuilder<DB, TB extends keyof DB, O>\n  implements\n    WhereInterface<DB, TB>,\n    MultiTableReturningInterface<DB, TB, O>,\n    OutputInterface<DB, TB, O, 'deleted'>,\n    OrderByInterface<DB, TB, {}>,\n    OperationNodeSource,\n    Compilable<O>,\n    Explainable,\n    Streamable<O>\n{\n  readonly #props: DeleteQueryBuilderProps\n\n  constructor(props: DeleteQueryBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  where<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): DeleteQueryBuilder<DB, TB, O>\n\n  where<E extends ExpressionOrFactory<DB, TB, SqlBool>>(\n    expression: E,\n  ): DeleteQueryBuilder<DB, TB, O>\n\n  where(...args: any[]): any {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithWhere(\n        this.#props.queryNode,\n        parseValueBinaryOperationOrExpression(args),\n      ),\n    })\n  }\n\n  whereRef<\n    LRE extends ReferenceExpression<DB, TB>,\n    RRE extends ReferenceExpression<DB, TB>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): DeleteQueryBuilder<DB, TB, O> {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithWhere(\n        this.#props.queryNode,\n        parseReferentialBinaryOperation(lhs, op, rhs),\n      ),\n    })\n  }\n\n  clearWhere(): DeleteQueryBuilder<DB, TB, O> {\n    return new DeleteQueryBuilder<DB, TB, O>({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithoutWhere(this.#props.queryNode),\n    })\n  }\n\n  /**\n   * Changes a `delete from` query into a `delete top from` query.\n   *\n   * `top` clause is only supported by some dialects like MS SQL Server.\n   *\n   * ### Examples\n   *\n   * Delete the first 5 rows:\n   *\n   * ```ts\n   * await db\n   *   .deleteFrom('person')\n   *   .top(5)\n   *   .where('age', '>', 18)\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * delete top(5) from \"person\" where \"age\" > @1\n   * ```\n   *\n   * Delete the first 50% of rows:\n   *\n   * ```ts\n   * await db\n   *   .deleteFrom('person')\n   *   .top(50, 'percent')\n   *   .where('age', '>', 18)\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * delete top(50) percent from \"person\" where \"age\" > @1\n   * ```\n   */\n  top(\n    expression: number | bigint,\n    modifiers?: 'percent',\n  ): DeleteQueryBuilder<DB, TB, O> {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithTop(\n        this.#props.queryNode,\n        parseTop(expression, modifiers),\n      ),\n    })\n  }\n\n  /**\n   * Adds a `using` clause to the query.\n   *\n   * This clause allows adding additional tables to the query for filtering/returning\n   * only. Usually a non-standard syntactic-sugar alternative to a `where` with a sub-query.\n   *\n   * ### Examples:\n   *\n   * ```ts\n   * await db\n   *   .deleteFrom('pet')\n   *   .using('person')\n   *   .whereRef('pet.owner_id', '=', 'person.id')\n   *   .where('person.first_name', '=', 'Bob')\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * delete from \"pet\"\n   * using \"person\"\n   * where \"pet\".\"owner_id\" = \"person\".\"id\"\n   *   and \"person\".\"first_name\" = $1\n   * ```\n   *\n   * On supported databases such as MySQL, this clause allows using joins, but requires\n   * at least one of the tables after the `from` keyword to be also named after\n   * the `using` keyword. See also {@link innerJoin}, {@link leftJoin}, {@link rightJoin}\n   * and {@link fullJoin}.\n   *\n   * ```ts\n   * await db\n   *   .deleteFrom('pet')\n   *   .using('pet')\n   *   .leftJoin('person', 'person.id', 'pet.owner_id')\n   *   .where('person.first_name', '=', 'Bob')\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * delete from `pet`\n   * using `pet`\n   * left join `person` on `person`.`id` = `pet`.`owner_id`\n   * where `person`.`first_name` = ?\n   * ```\n   *\n   * You can also chain multiple invocations of this method, or pass an array to\n   * a single invocation to name multiple tables.\n   *\n   * ```ts\n   * await db\n   *   .deleteFrom('toy')\n   *   .using(['pet', 'person'])\n   *   .whereRef('toy.pet_id', '=', 'pet.id')\n   *   .whereRef('pet.owner_id', '=', 'person.id')\n   *   .where('person.first_name', '=', 'Bob')\n   *   .returning('pet.name')\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * delete from \"toy\"\n   * using \"pet\", \"person\"\n   * where \"toy\".\"pet_id\" = \"pet\".\"id\"\n   *   and \"pet\".\"owner_id\" = \"person\".\"id\"\n   *   and \"person\".\"first_name\" = $1\n   * returning \"pet\".\"name\"\n   * ```\n   */\n  using<TE extends TableExpression<DB, keyof DB>>(\n    tables: TE[],\n  ): DeleteQueryBuilder<From<DB, TE>, FromTables<DB, TB, TE>, O>\n\n  using<TE extends TableExpression<DB, keyof DB>>(\n    table: TE,\n  ): DeleteQueryBuilder<From<DB, TE>, FromTables<DB, TB, TE>, O>\n\n  using(tables: TableExpressionOrList<any, any>): any {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: DeleteQueryNode.cloneWithUsing(\n        this.#props.queryNode,\n        parseTableExpressionOrList(tables),\n      ),\n    })\n  }\n\n  /**\n   * Joins another table to the query using an inner join.\n   *\n   * ### Examples\n   *\n   * Simple usage by providing a table name and two columns to join:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   // `select` needs to come after the call to `innerJoin` so\n   *   // that you can select from the joined table.\n   *   .select(['person.id', 'pet.name'])\n   *   .execute()\n   *\n   * result[0].id\n   * result[0].name\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"id\", \"pet\".\"name\"\n   * from \"person\"\n   * inner join \"pet\"\n   * on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ```\n   *\n   * You can give an alias for the joined table like this:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin('pet as p', 'p.owner_id', 'person.id')\n   *   .where('p.name', '=', 'Doggo')\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * inner join \"pet\" as \"p\"\n   * on \"p\".\"owner_id\" = \"person\".\"id\"\n   * where \"p\".name\" = $1\n   * ```\n   *\n   * You can provide a function as the second argument to get a join\n   * builder for creating more complex joins. The join builder has a\n   * bunch of `on*` methods for building the `on` clause of the join.\n   * There's basically an equivalent for every `where` method\n   * (`on`, `onRef`, `onExists` etc.). You can do all the same things\n   * with the `on` method that you can with the corresponding `where`\n   * method. See the `where` method documentation for more examples.\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin(\n   *     'pet',\n   *     (join) => join\n   *       .onRef('pet.owner_id', '=', 'person.id')\n   *       .on('pet.name', '=', 'Doggo')\n   *   )\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * inner join \"pet\"\n   * on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * and \"pet\".\"name\" = $1\n   * ```\n   *\n   * You can join a subquery by providing a select query (or a callback)\n   * as the first argument:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin(\n   *     db.selectFrom('pet')\n   *       .select(['owner_id', 'name'])\n   *       .where('name', '=', 'Doggo')\n   *       .as('doggos'),\n   *     'doggos.owner_id',\n   *     'person.id',\n   *   )\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * inner join (\n   *   select \"owner_id\", \"name\"\n   *   from \"pet\"\n   *   where \"name\" = $1\n   * ) as \"doggos\"\n   * on \"doggos\".\"owner_id\" = \"person\".\"id\"\n   * ```\n   */\n  innerJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(table: TE, k1: K1, k2: K2): DeleteQueryBuilderWithInnerJoin<DB, TB, O, TE>\n\n  innerJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(table: TE, callback: FN): DeleteQueryBuilderWithInnerJoin<DB, TB, O, TE>\n\n  innerJoin(...args: any): any {\n    return this.#join('InnerJoin', args)\n  }\n\n  /**\n   * Just like {@link innerJoin} but adds a left join instead of an inner join.\n   */\n  leftJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(table: TE, k1: K1, k2: K2): DeleteQueryBuilderWithLeftJoin<DB, TB, O, TE>\n\n  leftJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(table: TE, callback: FN): DeleteQueryBuilderWithLeftJoin<DB, TB, O, TE>\n\n  leftJoin(...args: any): any {\n    return this.#join('LeftJoin', args)\n  }\n\n  /**\n   * Just like {@link innerJoin} but adds a right join instead of an inner join.\n   */\n  rightJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(table: TE, k1: K1, k2: K2): DeleteQueryBuilderWithRightJoin<DB, TB, O, TE>\n\n  rightJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(table: TE, callback: FN): DeleteQueryBuilderWithRightJoin<DB, TB, O, TE>\n\n  rightJoin(...args: any): any {\n    return this.#join('RightJoin', args)\n  }\n\n  /**\n   * Just like {@link innerJoin} but adds a full join instead of an inner join.\n   */\n  fullJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(table: TE, k1: K1, k2: K2): DeleteQueryBuilderWithFullJoin<DB, TB, O, TE>\n\n  fullJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(table: TE, callback: FN): DeleteQueryBuilderWithFullJoin<DB, TB, O, TE>\n\n  fullJoin(...args: any): any {\n    return this.#join('FullJoin', args)\n  }\n\n  #join(joinType: JoinType, args: any[]): any {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithJoin(\n        this.#props.queryNode,\n        parseJoin(joinType, args),\n      ),\n    })\n  }\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selections: ReadonlyArray<SE>,\n  ): DeleteQueryBuilder<DB, TB, ReturningRow<DB, TB, O, SE>>\n\n  returning<CB extends SelectCallback<DB, TB>>(\n    callback: CB,\n  ): DeleteQueryBuilder<DB, TB, ReturningCallbackRow<DB, TB, O, CB>>\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selection: SE,\n  ): DeleteQueryBuilder<DB, TB, ReturningRow<DB, TB, O, SE>>\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selection: SelectArg<DB, TB, SE>,\n  ): DeleteQueryBuilder<DB, TB, ReturningRow<DB, TB, O, SE>> {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectArg(selection),\n      ),\n    })\n  }\n\n  /**\n   * Adds `returning *` or `returning table.*` clause to the query.\n   *\n   * ### Examples\n   *\n   * Return all columns.\n   *\n   * ```ts\n   * const pets = await db\n   *   .deleteFrom('pet')\n   *   .returningAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL)\n   *\n   * ```sql\n   * delete from \"pet\" returning *\n   * ```\n   *\n   * Return all columns from all tables\n   *\n   * ```ts\n   * const result = await db\n   *   .deleteFrom('toy')\n   *   .using(['pet', 'person'])\n   *   .whereRef('toy.pet_id', '=', 'pet.id')\n   *   .whereRef('pet.owner_id', '=', 'person.id')\n   *   .where('person.first_name', '=', 'Zoro')\n   *   .returningAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL)\n   *\n   * ```sql\n   * delete from \"toy\"\n   * using \"pet\", \"person\"\n   * where \"toy\".\"pet_id\" = \"pet\".\"id\"\n   * and \"pet\".\"owner_id\" = \"person\".\"id\"\n   * and \"person\".\"first_name\" = $1\n   * returning *\n   * ```\n   *\n   * Return all columns from a single table.\n   *\n   * ```ts\n   * const result = await db\n   *   .deleteFrom('toy')\n   *   .using(['pet', 'person'])\n   *   .whereRef('toy.pet_id', '=', 'pet.id')\n   *   .whereRef('pet.owner_id', '=', 'person.id')\n   *   .where('person.first_name', '=', 'Itachi')\n   *   .returningAll('pet')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL)\n   *\n   * ```sql\n   * delete from \"toy\"\n   * using \"pet\", \"person\"\n   * where \"toy\".\"pet_id\" = \"pet\".\"id\"\n   * and \"pet\".\"owner_id\" = \"person\".\"id\"\n   * and \"person\".\"first_name\" = $1\n   * returning \"pet\".*\n   * ```\n   *\n   * Return all columns from multiple tables.\n   *\n   * ```ts\n   * const result = await db\n   *   .deleteFrom('toy')\n   *   .using(['pet', 'person'])\n   *   .whereRef('toy.pet_id', '=', 'pet.id')\n   *   .whereRef('pet.owner_id', '=', 'person.id')\n   *   .where('person.first_name', '=', 'Luffy')\n   *   .returningAll(['toy', 'pet'])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL)\n   *\n   * ```sql\n   * delete from \"toy\"\n   * using \"pet\", \"person\"\n   * where \"toy\".\"pet_id\" = \"pet\".\"id\"\n   * and \"pet\".\"owner_id\" = \"person\".\"id\"\n   * and \"person\".\"first_name\" = $1\n   * returning \"toy\".*, \"pet\".*\n   * ```\n   */\n  returningAll<T extends TB>(\n    tables: ReadonlyArray<T>,\n  ): DeleteQueryBuilder<DB, TB, ReturningAllRow<DB, T, O>>\n\n  returningAll<T extends TB>(\n    table: T,\n  ): DeleteQueryBuilder<DB, TB, ReturningAllRow<DB, T, O>>\n\n  returningAll(): DeleteQueryBuilder<DB, TB, ReturningAllRow<DB, TB, O>>\n\n  returningAll(table?: any): any {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n\n  output<OE extends OutputExpression<DB, TB, 'deleted'>>(\n    selections: readonly OE[],\n  ): DeleteQueryBuilder<\n    DB,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output<CB extends OutputCallback<DB, TB, 'deleted'>>(\n    callback: CB,\n  ): DeleteQueryBuilder<\n    DB,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputCallback<CB>>\n  >\n\n  output<OE extends OutputExpression<DB, TB, 'deleted'>>(\n    selection: OE,\n  ): DeleteQueryBuilder<\n    DB,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output(args: any): any {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectArg(args),\n      ),\n    })\n  }\n\n  outputAll(\n    table: 'deleted',\n  ): DeleteQueryBuilder<DB, TB, ReturningAllRow<DB, TB, O>> {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n\n  /**\n   * Clears all `returning` clauses from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.deleteFrom('pet')\n   *   .returningAll()\n   *   .where('name', '=', 'Max')\n   *   .clearReturning()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * delete from \"pet\" where \"name\" = \"Max\"\n   * ```\n   */\n  clearReturning(): DeleteQueryBuilder<DB, TB, DeleteResult> {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithoutReturning(this.#props.queryNode),\n    })\n  }\n\n  /**\n   * Clears the `limit` clause from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.deleteFrom('pet')\n   *   .returningAll()\n   *   .where('name', '=', 'Max')\n   *   .limit(5)\n   *   .clearLimit()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * delete from \"pet\" where \"name\" = \"Max\" returning *\n   * ```\n   */\n  clearLimit(): DeleteQueryBuilder<DB, TB, O> {\n    return new DeleteQueryBuilder<DB, TB, O>({\n      ...this.#props,\n      queryNode: DeleteQueryNode.cloneWithoutLimit(this.#props.queryNode),\n    })\n  }\n\n  /**\n   * @description This is only supported by some dialects like MySQL or SQLite with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`.\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers?: OrderByModifiers,\n  ): DeleteQueryBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @description This is only supported by some dialects like MySQL or SQLite with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`.\n   * @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `orderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.\n   */\n  orderBy<\n    OE extends\n      | OrderByExpression<DB, TB, {}>\n      | DirectedOrderByStringReference<DB, TB, {}>,\n  >(exprs: ReadonlyArray<OE>): DeleteQueryBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @description This is only supported by some dialects like MySQL or SQLite with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`.\n   * @deprecated It does ~2.9x more compile-time instantiations compared to a `orderBy(expr, direction)` call.\n   */\n  orderBy<OE extends DirectedOrderByStringReference<DB, TB, {}>>(\n    expr: OE,\n  ): DeleteQueryBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @description This is only supported by some dialects like MySQL or SQLite with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`.\n   * @deprecated Use `orderBy(expr, (ob) => ...)` instead.\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers: Expression<any>,\n  ): DeleteQueryBuilder<DB, TB, O>\n\n  orderBy(...args: any[]): any {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOrderByItems(\n        this.#props.queryNode,\n        parseOrderBy(args),\n      ),\n    })\n  }\n\n  clearOrderBy(): DeleteQueryBuilder<DB, TB, O> {\n    return new DeleteQueryBuilder<DB, TB, O>({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithoutOrderBy(this.#props.queryNode),\n    })\n  }\n\n  /**\n   * Adds a limit clause to the query.\n   *\n   * A limit clause in a delete query is only supported by some dialects\n   * like MySQL.\n   *\n   * ### Examples\n   *\n   * Delete 5 oldest items in a table:\n   *\n   * ```ts\n   * await db\n   *   .deleteFrom('pet')\n   *   .orderBy('created_at')\n   *   .limit(5)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * delete from `pet` order by `created_at` limit ?\n   * ```\n   */\n  limit(limit: ValueExpression<DB, TB, number>): DeleteQueryBuilder<DB, TB, O> {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: DeleteQueryNode.cloneWithLimit(\n        this.#props.queryNode,\n        LimitNode.create(parseValueExpression(limit)),\n      ),\n    })\n  }\n\n  /**\n   * This can be used to add any additional SQL to the end of the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.deleteFrom('person')\n   *   .where('first_name', '=', 'John')\n   *   .modifyEnd(sql`-- This is a comment`)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * delete from `person`\n   * where `first_name` = \"John\" -- This is a comment\n   * ```\n   */\n  modifyEnd(modifier: Expression<any>): DeleteQueryBuilder<DB, TB, O> {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        modifier.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   *\n   * If you want to conditionally call a method on `this`, see\n   * the {@link $if} method.\n   *\n   * ### Examples\n   *\n   * The next example uses a helper function `log` to log a query:\n   *\n   * ```ts\n   * import type { Compilable } from 'kysely'\n   *\n   * function log<T extends Compilable>(qb: T): T {\n   *   console.log(qb.compile())\n   *   return qb\n   * }\n   *\n   * await db.deleteFrom('person')\n   *   .$call(log)\n   *   .execute()\n   * ```\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  /**\n   * Call `func(this)` if `condition` is true.\n   *\n   * This method is especially handy with optional selects. Any `returning` or `returningAll`\n   * method calls add columns as optional fields to the output type when called inside\n   * the `func` callback. This is because we can't know if those selections were actually\n   * made before running the code.\n   *\n   * You can also call any other methods inside the callback.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * async function deletePerson(id: number, returnLastName: boolean) {\n   *   return await db\n   *     .deleteFrom('person')\n   *     .where('id', '=', id)\n   *     .returning(['id', 'first_name'])\n   *     .$if(returnLastName, (qb) => qb.returning('last_name'))\n   *     .executeTakeFirstOrThrow()\n   * }\n   * ```\n   *\n   * Any selections added inside the `if` callback will be added as optional fields to the\n   * output type since we can't know if the selections were actually made before running\n   * the code. In the example above the return type of the `deletePerson` function is:\n   *\n   * ```ts\n   * Promise<{\n   *   id: number\n   *   first_name: string\n   *   last_name?: string\n   * }>\n   * ```\n   */\n  $if<O2>(\n    condition: boolean,\n    func: (qb: this) => DeleteQueryBuilder<any, any, O2>,\n  ): O2 extends DeleteResult\n    ? DeleteQueryBuilder<DB, TB, DeleteResult>\n    : O2 extends O & infer E\n      ? DeleteQueryBuilder<DB, TB, O & Partial<E>>\n      : DeleteQueryBuilder<DB, TB, Partial<O2>> {\n    if (condition) {\n      return func(this) as any\n    }\n\n    return new DeleteQueryBuilder({\n      ...this.#props,\n    }) as any\n  }\n\n  /**\n   * Change the output type of the query.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `DeleteQueryBuilder` with a new output type.\n   */\n  $castTo<C>(): DeleteQueryBuilder<DB, TB, C> {\n    return new DeleteQueryBuilder(this.#props)\n  }\n\n  /**\n   * Narrows (parts of) the output type of the query.\n   *\n   * Kysely tries to be as type-safe as possible, but in some cases we have to make\n   * compromises for better maintainability and compilation performance. At present,\n   * Kysely doesn't narrow the output type of the query when using {@link where} and {@link returning} or {@link returningAll}.\n   *\n   * This utility method is very useful for these situations, as it removes unncessary\n   * runtime assertion/guard code. Its input type is limited to the output type\n   * of the query, so you can't add a column that doesn't exist, or change a column's\n   * type to something that doesn't exist in its union type.\n   *\n   * ### Examples\n   *\n   * Turn this code:\n   *\n   * ```ts\n   * import type { Person } from 'type-editor' // imaginary module\n   *\n   * const person = await db.deleteFrom('person')\n   *   .where('id', '=', 3)\n   *   .where('nullable_column', 'is not', null)\n   *   .returningAll()\n   *   .executeTakeFirstOrThrow()\n   *\n   * if (isWithNoNullValue(person)) {\n   *   functionThatExpectsPersonWithNonNullValue(person)\n   * }\n   *\n   * function isWithNoNullValue(person: Person): person is Person & { nullable_column: string } {\n   *   return person.nullable_column != null\n   * }\n   * ```\n   *\n   * Into this:\n   *\n   * ```ts\n   * import type { NotNull } from 'kysely'\n   *\n   * const person = await db.deleteFrom('person')\n   *   .where('id', '=', 3)\n   *   .where('nullable_column', 'is not', null)\n   *   .returningAll()\n   *   .$narrowType<{ nullable_column: NotNull }>()\n   *   .executeTakeFirstOrThrow()\n   *\n   * functionThatExpectsPersonWithNonNullValue(person)\n   * ```\n   */\n  $narrowType<T>(): DeleteQueryBuilder<DB, TB, NarrowPartial<O, T>> {\n    return new DeleteQueryBuilder(this.#props)\n  }\n\n  /**\n   * Asserts that query's output row type equals the given type `T`.\n   *\n   * This method can be used to simplify excessively complex types to make TypeScript happy\n   * and much faster.\n   *\n   * Kysely uses complex type magic to achieve its type safety. This complexity is sometimes too much\n   * for TypeScript and you get errors like this:\n   *\n   * ```\n   * error TS2589: Type instantiation is excessively deep and possibly infinite.\n   * ```\n   *\n   * In these case you can often use this method to help TypeScript a little bit. When you use this\n   * method to assert the output type of a query, Kysely can drop the complex output type that\n   * consists of multiple nested helper types and replace it with the simple asserted type.\n   *\n   * Using this method doesn't reduce type safety at all. You have to pass in a type that is\n   * structurally equal to the current type.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { Species } from 'type-editor' // imaginary module\n   *\n   * async function deletePersonAndPets(personId: number) {\n   *   return await db\n   *     .with('deleted_person', (qb) => qb\n   *        .deleteFrom('person')\n   *        .where('id', '=', personId)\n   *        .returning('first_name')\n   *        .$assertType<{ first_name: string }>()\n   *     )\n   *     .with('deleted_pets', (qb) => qb\n   *       .deleteFrom('pet')\n   *       .where('owner_id', '=', personId)\n   *       .returning(['name as pet_name', 'species'])\n   *       .$assertType<{ pet_name: string, species: Species }>()\n   *     )\n   *     .selectFrom(['deleted_person', 'deleted_pets'])\n   *     .selectAll()\n   *     .execute()\n   * }\n   * ```\n   */\n  $assertType<T extends O>(): O extends T\n    ? DeleteQueryBuilder<DB, TB, T>\n    : KyselyTypeError<`$assertType() call failed: The type passed in is not equal to the output type of the query.`> {\n    return new DeleteQueryBuilder(this.#props) as unknown as any\n  }\n\n  /**\n   * Returns a copy of this DeleteQueryBuilder instance with the given plugin installed.\n   */\n  withPlugin(plugin: KyselyPlugin): DeleteQueryBuilder<DB, TB, O> {\n    return new DeleteQueryBuilder({\n      ...this.#props,\n      executor: this.#props.executor.withPlugin(plugin),\n    })\n  }\n\n  toOperationNode(): DeleteQueryNode {\n    return this.#props.executor.transformQuery(\n      this.#props.queryNode,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery<SimplifyResult<O>> {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  /**\n   * Executes the query and returns an array of rows.\n   *\n   * Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.\n   */\n  async execute(): Promise<SimplifyResult<O>[]> {\n    const compiledQuery = this.compile()\n\n    const result = await this.#props.executor.executeQuery<O>(compiledQuery)\n\n    const { adapter } = this.#props.executor\n    const query = compiledQuery.query as DeleteQueryNode\n\n    if (\n      (query.returning && adapter.supportsReturning) ||\n      (query.output && adapter.supportsOutput)\n    ) {\n      return result.rows as any\n    }\n\n    return [new DeleteResult(result.numAffectedRows ?? BigInt(0)) as any]\n  }\n\n  /**\n   * Executes the query and returns the first result or undefined if\n   * the query returned no result.\n   */\n  async executeTakeFirst(): Promise<SimplifySingleResult<O>> {\n    const [result] = await this.execute()\n    return result as SimplifySingleResult<O>\n  }\n\n  /**\n   * Executes the query and returns the first result or throws if\n   * the query returned no result.\n   *\n   * By default an instance of {@link NoResultError} is thrown, but you can\n   * provide a custom error class, or callback as the only argument to throw a different\n   * error.\n   */\n  async executeTakeFirstOrThrow(\n    errorConstructor:\n      | NoResultErrorConstructor\n      | ((node: QueryNode) => Error) = NoResultError,\n  ): Promise<SimplifyResult<O>> {\n    const result = await this.executeTakeFirst()\n\n    if (result === undefined) {\n      const error = isNoResultErrorConstructor(errorConstructor)\n        ? new errorConstructor(this.toOperationNode())\n        : errorConstructor(this.toOperationNode())\n\n      throw error\n    }\n\n    return result as SimplifyResult<O>\n  }\n\n  async *stream(chunkSize: number = 100): AsyncIterableIterator<O> {\n    const compiledQuery = this.compile()\n\n    const stream = this.#props.executor.stream<O>(compiledQuery, chunkSize)\n\n    for await (const item of stream) {\n      yield* item.rows\n    }\n  }\n\n  async explain<ER extends Record<string, any> = Record<string, any>>(\n    format?: ExplainFormat,\n    options?: Expression<any>,\n  ): Promise<ER[]> {\n    const builder = new DeleteQueryBuilder<DB, TB, ER>({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithExplain(\n        this.#props.queryNode,\n        format,\n        options,\n      ),\n    })\n\n    return await builder.execute()\n  }\n}\n\nexport interface DeleteQueryBuilderProps {\n  readonly queryId: QueryId\n  readonly queryNode: DeleteQueryNode\n  readonly executor: QueryExecutor\n}\n\nexport type DeleteQueryBuilderWithInnerJoin<\n  DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? InnerJoinedBuilder<DB, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? DeleteQueryBuilder<DB, TB | TE, O>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? InnerJoinedBuilder<DB, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? InnerJoinedBuilder<DB, TB, O, QA, QO>\n        : never\n\ntype InnerJoinedBuilder<\n  DB,\n  TB extends keyof DB,\n  O,\n  A extends string,\n  R,\n> = A extends keyof DB\n  ? DeleteQueryBuilder<InnerJoinedDB<DB, A, R>, TB | A, O>\n  : // Much faster non-recursive solution for the simple case.\n    DeleteQueryBuilder<DB & ShallowRecord<A, R>, TB | A, O>\n\ntype InnerJoinedDB<DB, A extends string, R> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A ? R : C extends keyof DB ? DB[C] : never\n}>\n\nexport type DeleteQueryBuilderWithLeftJoin<\n  DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? LeftJoinedBuilder<DB, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? LeftJoinedBuilder<DB, TB, O, TE, DB[TE]>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? LeftJoinedBuilder<DB, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? LeftJoinedBuilder<DB, TB, O, QA, QO>\n        : never\n\ntype LeftJoinedBuilder<\n  DB,\n  TB extends keyof DB,\n  O,\n  A extends keyof any,\n  R,\n> = A extends keyof DB\n  ? DeleteQueryBuilder<LeftJoinedDB<DB, A, R>, TB | A, O>\n  : // Much faster non-recursive solution for the simple case.\n    DeleteQueryBuilder<DB & ShallowRecord<A, Nullable<R>>, TB | A, O>\n\ntype LeftJoinedDB<DB, A extends keyof any, R> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A\n    ? Nullable<R>\n    : C extends keyof DB\n      ? DB[C]\n      : never\n}>\n\nexport type DeleteQueryBuilderWithRightJoin<\n  DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? RightJoinedBuilder<DB, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? RightJoinedBuilder<DB, TB, O, TE, DB[TE]>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? RightJoinedBuilder<DB, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? RightJoinedBuilder<DB, TB, O, QA, QO>\n        : never\n\ntype RightJoinedBuilder<\n  DB,\n  TB extends keyof DB,\n  O,\n  A extends keyof any,\n  R,\n> = DeleteQueryBuilder<RightJoinedDB<DB, TB, A, R>, TB | A, O>\n\ntype RightJoinedDB<\n  DB,\n  TB extends keyof DB,\n  A extends keyof any,\n  R,\n> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A\n    ? R\n    : C extends TB\n      ? Nullable<DB[C]>\n      : C extends keyof DB\n        ? DB[C]\n        : never\n}>\n\nexport type DeleteQueryBuilderWithFullJoin<\n  DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? OuterJoinedBuilder<DB, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? OuterJoinedBuilder<DB, TB, O, TE, DB[TE]>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? OuterJoinedBuilder<DB, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? OuterJoinedBuilder<DB, TB, O, QA, QO>\n        : never\n\ntype OuterJoinedBuilder<\n  DB,\n  TB extends keyof DB,\n  O,\n  A extends keyof any,\n  R,\n> = DeleteQueryBuilder<OuterJoinedBuilderDB<DB, TB, A, R>, TB | A, O>\n\ntype OuterJoinedBuilderDB<\n  DB,\n  TB extends keyof DB,\n  A extends keyof any,\n  R,\n> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A\n    ? Nullable<R>\n    : C extends TB\n      ? Nullable<DB[C]>\n      : C extends keyof DB\n        ? DB[C]\n        : never\n}>\n"
  },
  {
    "path": "src/query-builder/delete-result.ts",
    "content": "export class DeleteResult {\n  readonly numDeletedRows: bigint\n\n  constructor(numDeletedRows: bigint) {\n    this.numDeletedRows = numDeletedRows\n  }\n}\n"
  },
  {
    "path": "src/query-builder/function-module.ts",
    "content": "import { ExpressionWrapper } from '../expression/expression-wrapper.js'\nimport type { Expression } from '../expression/expression.js'\nimport { AggregateFunctionNode } from '../operation-node/aggregate-function-node.js'\nimport { FunctionNode } from '../operation-node/function-node.js'\nimport type {\n  ExtractTypeFromCoalesce1,\n  ExtractTypeFromCoalesce3,\n  ExtractTypeFromCoalesce2,\n  ExtractTypeFromCoalesce4,\n  ExtractTypeFromCoalesce5,\n} from '../parser/coalesce-parser.js'\nimport {\n  type ExtractTypeFromReferenceExpression,\n  type ReferenceExpression,\n  type StringReference,\n  parseReferenceExpressionOrList,\n  type ExtractTypeFromStringReference,\n} from '../parser/reference-parser.js'\nimport { parseSelectAll } from '../parser/select-parser.js'\nimport type { KyselyTypeError } from '../util/type-error.js'\nimport type {\n  IsNever,\n  ShallowDehydrateObject,\n  ShallowDehydrateValue,\n  Simplify,\n} from '../util/type-utils.js'\nimport { AggregateFunctionBuilder } from './aggregate-function-builder.js'\nimport type { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js'\nimport { isString } from '../util/object-utils.js'\nimport { parseTable } from '../parser/table-parser.js'\nimport type { Selectable, SelectType } from '../util/column-type.js'\n\n/**\n * Helpers for type safe SQL function calls.\n *\n * You can always use the {@link sql} tag to call functions and build arbitrary\n * expressions. This module simply has shortcuts for most common function calls.\n *\n * ### Examples\n *\n * <!-- siteExample(\"select\", \"Function calls\", 60) -->\n *\n * This example shows how to create function calls. These examples also work in any\n * other place (`where` calls, updates, inserts etc.). The only difference is that you\n * leave out the alias (the `as` call) if you use these in any other place than `select`.\n *\n * ```ts\n * import { sql } from 'kysely'\n *\n * const result = await db.selectFrom('person')\n *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n *   .select(({ fn, val, ref }) => [\n *     'person.id',\n *\n *     // The `fn` module contains the most common\n *     // functions.\n *     fn.count<number>('pet.id').as('pet_count'),\n *\n *     // You can call any function by calling `fn`\n *     // directly. The arguments are treated as column\n *     // references by default. If you want  to pass in\n *     // values, use the `val` function.\n *     fn<string>('concat', [\n *       val('Ms. '),\n *       'first_name',\n *       val(' '),\n *       'last_name'\n *     ]).as('full_name_with_title'),\n *\n *     // You can call any aggregate function using the\n *     // `fn.agg` function.\n *     fn.agg<string[]>('array_agg', ['pet.name']).as('pet_names'),\n *\n *     // And once again, you can use the `sql`\n *     // template tag. The template tag substitutions\n *     // are treated as values by default. If you want\n *     // to reference columns, you can use the `ref`\n *     // function.\n *     sql<string>`concat(\n *       ${ref('first_name')},\n *       ' ',\n *       ${ref('last_name')}\n *     )`.as('full_name')\n *   ])\n *   .groupBy('person.id')\n *   .having((eb) => eb.fn.count('pet.id'), '>', 10)\n *   .execute()\n * ```\n *\n * The generated SQL (PostgreSQL):\n *\n * ```sql\n * select\n *   \"person\".\"id\",\n *   count(\"pet\".\"id\") as \"pet_count\",\n *   concat($1, \"first_name\", $2, \"last_name\") as \"full_name_with_title\",\n *   array_agg(\"pet\".\"name\") as \"pet_names\",\n *   concat(\"first_name\", ' ', \"last_name\") as \"full_name\"\n * from \"person\"\n * inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"\n * group by \"person\".\"id\"\n * having count(\"pet\".\"id\") > $3\n * ```\n */\nexport interface FunctionModule<DB, TB extends keyof DB> {\n  /**\n   * Creates a function call.\n   *\n   * To create an aggregate function call, use {@link FunctionModule.agg}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where(db.fn('upper', ['first_name']), '=', 'JENNIFER')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*\n   * from \"person\"\n   * where upper(\"first_name\") = $1\n   * ```\n   *\n   * If you prefer readability over type-safety, you can always use raw `sql`:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where(sql<string>`upper(first_name)`, '=', 'JENNIFER')\n   *   .execute()\n   * ```\n   */\n  <O, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(\n    name: string,\n    args?: ReadonlyArray<RE>,\n  ): ExpressionWrapper<DB, TB, O>\n\n  /**\n   * Creates an aggregate function call.\n   *\n   * This is a specialized version of the `fn` method, that returns an {@link AggregateFunctionBuilder}\n   * instance. A builder that allows you to chain additional methods such as `distinct`,\n   * `filterWhere` and `over`.\n   *\n   * See {@link avg}, {@link count}, {@link countAll}, {@link max}, {@link min}, {@link sum}\n   * shortcuts of common aggregate functions.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(({ fn }) => [\n   *     fn.agg<number>('rank').over().as('rank'),\n   *     fn.agg<string>('group_concat', ['first_name']).distinct().as('first_names')\n   *   ])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * select rank() over() as \"rank\",\n   *   group_concat(distinct \"first_name\") as \"first_names\"\n   * from \"person\"\n   * ```\n   */\n  agg<O, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(\n    name: string,\n    args?: ReadonlyArray<RE>,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  /**\n   * Calls the `avg` function for the column or expression given as the argument.\n   *\n   * This sql function calculates the average value for a given column.\n   *\n   * For additional functionality such as distinct, filtering and window functions,\n   * refer to {@link AggregateFunctionBuilder}. An instance of this builder is\n   * returned when calling this function.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.avg('price').as('avg_price'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select avg(\"price\") as \"avg_price\" from \"toy\"\n   * ```\n   *\n   * If this function is used in a `select` statement, the type of the selected\n   * expression will be `number | string` by default. This is because Kysely can't know the\n   * type the db driver outputs. Sometimes the output can be larger than the largest\n   * JavaScript number and a string is returned instead. Most drivers allow you\n   * to configure the output type of large numbers and Kysely can't know if you've\n   * done so.\n   *\n   * You can specify the output type of the expression by providing the type as\n   * the first type argument:\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.avg<number>('price').as('avg_price'))\n   *   .execute()\n   * ```\n   *\n   * Sometimes a null is returned, e.g. when row count is 0, and no `group by`\n   * was used. It is highly recommended to include null in the output type union\n   * and handle null values in post-execute code, or wrap the function with a {@link coalesce}\n   * function.\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.avg<number | null>('price').as('avg_price'))\n   *   .execute()\n   * ```\n   */\n  avg<\n    O extends number | string | null = number | string,\n    RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>,\n  >(\n    expr: RE,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  /**\n   * Calls the `coalesce` function for given arguments.\n   *\n   * This sql function returns the first non-null value from left to right, commonly\n   * used to provide a default scalar for nullable columns or functions.\n   *\n   * If this function is used in a `select` statement, the type of the selected\n   * expression is inferred in the same manner that the sql function computes.\n   * A union of arguments' types - if a non-nullable argument exists, it stops\n   * there (ignoring any further arguments' types) and exludes null from the final\n   * union type.\n   *\n   * `(string | null, number | null)` is inferred as `string | number | null`.\n   *\n   * `(string | null, number, Date | null)` is inferred as `string | number`.\n   *\n   * `(number, string | null)` is inferred as `number`.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.selectFrom('person')\n   *   .select((eb) => eb.fn.coalesce('nullable_column', sql.lit('<unknown>')).as('column'))\n   *   .where('first_name', '=', 'Jessie')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select coalesce(\"nullable_column\", '<unknown>') as \"column\" from \"person\" where \"first_name\" = $1\n   * ```\n   *\n   * You can combine this function with other helpers in this module:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select((eb) => eb.fn.coalesce(eb.fn.avg<number | null>('age'), eb.lit(0)).as('avg_age'))\n   *   .where('first_name', '=', 'Jennifer')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select coalesce(avg(\"age\"), 0) as \"avg_age\" from \"person\" where \"first_name\" = $1\n   * ```\n   */\n  coalesce<V1 extends ReferenceExpression<DB, TB>>(\n    v1: V1,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromCoalesce1<DB, TB, V1>>\n\n  coalesce<\n    V1 extends ReferenceExpression<DB, TB>,\n    V2 extends ReferenceExpression<DB, TB>,\n  >(\n    v1: V1,\n    v2: V2,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromCoalesce2<DB, TB, V1, V2>>\n\n  coalesce<\n    V1 extends ReferenceExpression<DB, TB>,\n    V2 extends ReferenceExpression<DB, TB>,\n    V3 extends ReferenceExpression<DB, TB>,\n  >(\n    v1: V1,\n    v2: V2,\n    v3: V3,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromCoalesce3<DB, TB, V1, V2, V3>>\n\n  coalesce<\n    V1 extends ReferenceExpression<DB, TB>,\n    V2 extends ReferenceExpression<DB, TB>,\n    V3 extends ReferenceExpression<DB, TB>,\n    V4 extends ReferenceExpression<DB, TB>,\n  >(\n    v1: V1,\n    v2: V2,\n    v3: V3,\n    v4: V4,\n  ): ExpressionWrapper<DB, TB, ExtractTypeFromCoalesce4<DB, TB, V1, V2, V3, V4>>\n\n  coalesce<\n    V1 extends ReferenceExpression<DB, TB>,\n    V2 extends ReferenceExpression<DB, TB>,\n    V3 extends ReferenceExpression<DB, TB>,\n    V4 extends ReferenceExpression<DB, TB>,\n    V5 extends ReferenceExpression<DB, TB>,\n  >(\n    v1: V1,\n    v2: V2,\n    v3: V3,\n    v4: V4,\n    v5: V5,\n  ): ExpressionWrapper<\n    DB,\n    TB,\n    ExtractTypeFromCoalesce5<DB, TB, V1, V2, V3, V4, V5>\n  >\n\n  /**\n   * Calls the `count` function for the column or expression given as the argument.\n   *\n   * When called with a column as argument, this sql function counts the number of rows where there\n   * is a non-null value in that column.\n   *\n   * For counting all rows nulls included (`count(*)`), see {@link countAll}.\n   *\n   * For additional functionality such as distinct, filtering and window functions,\n   * refer to {@link AggregateFunctionBuilder}. An instance of this builder is\n   * returned when calling this function.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.count('id').as('num_toys'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select count(\"id\") as \"num_toys\" from \"toy\"\n   * ```\n   *\n   * If this function is used in a `select` statement, the type of the selected\n   * expression will be `number | string | bigint` by default. This is because\n   * Kysely can't know the type the db driver outputs. Sometimes the output can\n   * be larger than the largest JavaScript number and a string is returned instead.\n   * Most drivers allow you to configure the output type of large numbers and Kysely\n   * can't know if you've done so.\n   *\n   * You can specify the output type of the expression by providing\n   * the type as the first type argument:\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.count<number>('id').as('num_toys'))\n   *   .execute()\n   * ```\n   */\n  count<\n    O extends number | string | bigint,\n    RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>,\n  >(\n    expr: RE,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  /**\n   * Calls the `count` function with `*` or `table.*` as argument.\n   *\n   * When called with `*` as argument, this sql function counts the number of rows,\n   * nulls included.\n   *\n   * For counting rows with non-null values in a given column (`count(column)`),\n   * see {@link count}.\n   *\n   * For additional functionality such as filtering and window functions, refer\n   * to {@link AggregateFunctionBuilder}. An instance of this builder is returned\n   * when calling this function.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.countAll().as('num_toys'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select count(*) as \"num_toys\" from \"toy\"\n   * ```\n   *\n   * If this is used in a `select` statement, the type of the selected expression\n   * will be `number | string | bigint` by default. This is because Kysely\n   * can't know the type the db driver outputs. Sometimes the output can be larger\n   * than the largest JavaScript number and a string is returned instead. Most\n   * drivers allow you to configure the output type of large numbers and Kysely\n   * can't know if you've done so.\n   *\n   * You can specify the output type of the expression by providing\n   * the type as the first type argument:\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.countAll<number>().as('num_toys'))\n   *   .execute()\n   * ```\n   *\n   * Some databases, such as PostgreSQL, support scoping the function to a specific\n   * table:\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .innerJoin('pet', 'pet.id', 'toy.pet_id')\n   *   .select((eb) => eb.fn.countAll('toy').as('num_toys'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select count(\"toy\".*) as \"num_toys\"\n   * from \"toy\" inner join \"pet\" on \"pet\".\"id\" = \"toy\".\"pet_id\"\n   * ```\n   */\n  countAll<O extends number | string | bigint, T extends TB = TB>(\n    table: T,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  countAll<O extends number | string | bigint>(): AggregateFunctionBuilder<\n    DB,\n    TB,\n    O\n  >\n\n  /**\n   * Calls the `max` function for the column or expression given as the argument.\n   *\n   * This sql function calculates the maximum value for a given column.\n   *\n   * For additional functionality such as distinct, filtering and window functions,\n   * refer to {@link AggregateFunctionBuilder}. An instance of this builder is\n   * returned when calling this function.\n   *\n   * If this function is used in a `select` statement, the type of the selected\n   * expression will be the referenced column's type. This is because the result\n   * is within the column's value range.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.max('price').as('max_price'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select max(\"price\") as \"max_price\" from \"toy\"\n   * ```\n   *\n   * Sometimes a null is returned, e.g. when row count is 0, and no `group by`\n   * was used. It is highly recommended to include null in the output type union\n   * and handle null values in post-execute code, or wrap the function with a {@link coalesce}\n   * function.\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.max<number | null>('price').as('max_price'))\n   *   .execute()\n   * ```\n   */\n  max<\n    O extends number | string | Date | bigint | null = never,\n    RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>,\n  >(\n    expr: RE,\n  ): AggregateFunctionBuilder<\n    DB,\n    TB,\n    IsNever<O> extends true\n      ? ExtractTypeFromReferenceExpression<\n          DB,\n          TB,\n          RE,\n          number | string | Date | bigint\n        >\n      : O\n  >\n\n  /**\n   * Calls the `min` function for the column or expression given as the argument.\n   *\n   * This sql function calculates the minimum value for a given column.\n   *\n   * For additional functionality such as distinct, filtering and window functions,\n   * refer to {@link AggregateFunctionBuilder}. An instance of this builder is\n   * returned when calling this function.\n   *\n   * If this function is used in a `select` statement, the type of the selected\n   * expression will be the referenced column's type. This is because the result\n   * is within the column's value range.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.min('price').as('min_price'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select min(\"price\") as \"min_price\" from \"toy\"\n   * ```\n   *\n   * Sometimes a null is returned, e.g. when row count is 0, and no `group by`\n   * was used. It is highly recommended to include null in the output type union\n   * and handle null values in post-execute code, or wrap the function with a {@link coalesce}\n   * function.\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.min<number | null>('price').as('min_price'))\n   *   .execute()\n   * ```\n   */\n  min<\n    O extends number | string | Date | bigint | null = never,\n    RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>,\n  >(\n    expr: RE,\n  ): AggregateFunctionBuilder<\n    DB,\n    TB,\n    IsNever<O> extends true\n      ? ExtractTypeFromReferenceExpression<\n          DB,\n          TB,\n          RE,\n          number | string | Date | bigint\n        >\n      : O\n  >\n\n  /**\n   * Calls the `sum` function for the column or expression given as the argument.\n   *\n   * This sql function sums the values of a given column.\n   *\n   * For additional functionality such as distinct, filtering and window functions,\n   * refer to {@link AggregateFunctionBuilder}. An instance of this builder is\n   * returned when calling this function.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.sum('price').as('total_price'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select sum(\"price\") as \"total_price\" from \"toy\"\n   * ```\n   *\n   * If this function is used in a `select` statement, the type of the selected\n   * expression will be `number | string` by default. This is because Kysely can't know the\n   * type the db driver outputs. Sometimes the output can be larger than the largest\n   * JavaScript number and a string is returned instead. Most drivers allow you\n   * to configure the output type of large numbers and Kysely can't know if you've\n   * done so.\n   *\n   * You can specify the output type of the expression by providing the type as\n   * the first type argument:\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.sum<number>('price').as('total_price'))\n   *   .execute()\n   * ```\n   *\n   * Sometimes a null is returned, e.g. when row count is 0, and no `group by`\n   * was used. It is highly recommended to include null in the output type union\n   * and handle null values in post-execute code, or wrap the function with a {@link coalesce}\n   * function.\n   *\n   * ```ts\n   * await db.selectFrom('toy')\n   *   .select((eb) => eb.fn.sum<number | null>('price').as('total_price'))\n   *   .execute()\n   * ```\n   */\n  sum<\n    O extends number | string | bigint | null = number | string | bigint,\n    RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>,\n  >(\n    expr: RE,\n  ): AggregateFunctionBuilder<DB, TB, O>\n\n  /**\n   * Calls the `any` function for the column or expression given as the argument.\n   *\n   * The argument must be a subquery or evaluate to an array.\n   *\n   * ### Examples\n   *\n   * In the following example, `nicknames` is assumed to be a column of type `string[]`:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .selectAll('person')\n   *   .where((eb) => eb(\n   *     eb.val('Jen'), '=', eb.fn.any('person.nicknames')\n   *   ))\n   *   .execute()\n   * ```\n   *\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   \"person\".*\n   * from\n   *   \"person\"\n   * where\n   *  $1 = any(\"person\".\"nicknames\")\n   * ```\n   */\n  any<RE extends StringReference<DB, TB>>(\n    expr: RE,\n  ): Exclude<\n    ExtractTypeFromReferenceExpression<DB, TB, RE>,\n    null\n  > extends ReadonlyArray<infer I>\n    ? ExpressionWrapper<DB, TB, I>\n    : KyselyTypeError<'any(expr) call failed: expr must be an array'>\n\n  any<T>(\n    subquery: SelectQueryBuilderExpression<Record<string, T>>,\n  ): ExpressionWrapper<DB, TB, T>\n\n  any<T>(expr: Expression<ReadonlyArray<T>>): ExpressionWrapper<DB, TB, T>\n\n  /**\n   * Creates a `json_agg` function call.\n   *\n   * This is only supported by some dialects like PostgreSQL.\n   *\n   * ### Examples\n   *\n   * You can use it on table expressions:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .select((eb) => ['first_name', eb.fn.jsonAgg('pet').as('pets')])\n   *   .groupBy('person.first_name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\", json_agg(\"pet\") as \"pets\"\n   * from \"person\"\n   * inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * group by \"person\".\"first_name\"\n   * ```\n   *\n   * or on columns:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .select((eb) => [\n   *     'first_name',\n   *     eb.fn.jsonAgg('pet.name').as('pet_names'),\n   *   ])\n   *   .groupBy('person.first_name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\", json_agg(\"pet\".\"name\") AS \"pet_names\"\n   * from \"person\"\n   * inner join \"pet\" ON \"pet\".\"owner_id\" = \"person\".\"id\"\n   * group by \"person\".\"first_name\"\n   * ```\n   */\n  jsonAgg<T extends (TB & string) | Expression<unknown>>(\n    table: T,\n  ): AggregateFunctionBuilder<\n    DB,\n    TB,\n    T extends TB\n      ? Simplify<ShallowDehydrateObject<Selectable<DB[T]>>>[]\n      : T extends Expression<infer O>\n        ? Simplify<ShallowDehydrateObject<O>>[]\n        : never\n  >\n\n  jsonAgg<RE extends StringReference<DB, TB>>(\n    column: RE,\n  ): AggregateFunctionBuilder<\n    DB,\n    TB,\n    | ShallowDehydrateValue<\n        SelectType<ExtractTypeFromStringReference<DB, TB, RE>>\n      >[]\n    | null\n  >\n\n  /**\n   * Creates a to_json function call.\n   *\n   * This function is only available on PostgreSQL.\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .select((eb) => ['first_name', eb.fn.toJson('pet').as('pet')])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\", to_json(\"pet\") as \"pet\"\n   * from \"person\"\n   * inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ```\n   */\n  toJson<T extends (TB & string) | Expression<unknown>>(\n    table: T,\n  ): ExpressionWrapper<\n    DB,\n    TB,\n    T extends TB\n      ? Simplify<ShallowDehydrateObject<Selectable<DB[T]>>>\n      : T extends Expression<infer O>\n        ? Simplify<ShallowDehydrateObject<O>>\n        : never\n  >\n}\n\nexport function createFunctionModule<DB, TB extends keyof DB>(): FunctionModule<\n  DB,\n  TB\n> {\n  const fn = <T>(\n    name: string,\n    args?: ReadonlyArray<ReferenceExpression<DB, TB>>,\n  ): ExpressionWrapper<DB, TB, T> => {\n    return new ExpressionWrapper(\n      FunctionNode.create(name, parseReferenceExpressionOrList(args ?? [])),\n    )\n  }\n\n  const agg = <O>(\n    name: string,\n    args?: ReadonlyArray<ReferenceExpression<DB, TB>>,\n  ): AggregateFunctionBuilder<DB, TB, O> => {\n    return new AggregateFunctionBuilder({\n      aggregateFunctionNode: AggregateFunctionNode.create(\n        name,\n        args ? parseReferenceExpressionOrList(args) : undefined,\n      ),\n    })\n  }\n\n  return Object.assign(fn, {\n    agg,\n\n    avg<\n      O extends number | string | null = number | string,\n      C extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>,\n    >(column: C): AggregateFunctionBuilder<DB, TB, O> {\n      return agg('avg', [column])\n    },\n\n    coalesce(...values: any[]): ExpressionWrapper<DB, TB, any> {\n      return fn('coalesce', values)\n    },\n\n    count<\n      O extends number | string | bigint,\n      C extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>,\n    >(column: C): AggregateFunctionBuilder<DB, TB, O> {\n      return agg('count', [column])\n    },\n\n    countAll(table?: string): any {\n      return new AggregateFunctionBuilder({\n        aggregateFunctionNode: AggregateFunctionNode.create(\n          'count',\n          parseSelectAll(table),\n        ),\n      })\n    },\n\n    max(column: any): any {\n      return agg('max', [column])\n    },\n\n    min(column: any): any {\n      return agg('min', [column])\n    },\n\n    sum<\n      O extends number | string | bigint | null = number | string | bigint,\n      C extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>,\n    >(column: C): AggregateFunctionBuilder<DB, TB, O> {\n      return agg('sum', [column])\n    },\n\n    any<RE extends ReferenceExpression<DB, TB>>(column: RE): any {\n      return fn('any', [column])\n    },\n\n    jsonAgg(table: string | Expression<unknown>): any {\n      return new AggregateFunctionBuilder({\n        aggregateFunctionNode: AggregateFunctionNode.create('json_agg', [\n          isString(table) ? parseTable(table) : table.toOperationNode(),\n        ]),\n      })\n    },\n\n    toJson(table: string | Expression<unknown>): any {\n      return new ExpressionWrapper(\n        FunctionNode.create('to_json', [\n          isString(table) ? parseTable(table) : table.toOperationNode(),\n        ]),\n      )\n    },\n  })\n}\n"
  },
  {
    "path": "src/query-builder/having-interface.ts",
    "content": "import type {\n  ComparisonOperatorExpression,\n  OperandValueExpressionOrList,\n} from '../parser/binary-operation-parser.js'\nimport type { ExpressionOrFactory } from '../parser/expression-parser.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport type { SqlBool } from '../util/type-utils.js'\n\nexport interface HavingInterface<DB, TB extends keyof DB> {\n  /**\n   * Just like {@link WhereInterface.where | where} but adds a `having` statement\n   * instead of a `where` statement.\n   */\n  having<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): HavingInterface<DB, TB>\n\n  having<E>(expression: E): HavingInterface<DB, TB>\n\n  /**\n   * Just like {@link WhereInterface.whereRef | whereRef} but adds a `having` statement\n   * instead of a `where` statement.\n   */\n  havingRef<\n    LRE extends ReferenceExpression<DB, TB>,\n    RRE extends ReferenceExpression<DB, TB>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): HavingInterface<DB, TB>\n}\n"
  },
  {
    "path": "src/query-builder/insert-query-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport {\n  parseSelectArg,\n  parseSelectAll,\n  type SelectExpression,\n  type SelectArg,\n  type SelectCallback,\n} from '../parser/select-parser.js'\nimport {\n  type InsertExpression,\n  parseInsertExpression,\n} from '../parser/insert-values-parser.js'\nimport { InsertQueryNode } from '../operation-node/insert-query-node.js'\nimport { QueryNode } from '../operation-node/query-node.js'\nimport type {\n  NarrowPartial,\n  SimplifyResult,\n  SimplifySingleResult,\n} from '../util/type-utils.js'\nimport {\n  type UpdateObjectExpression,\n  parseUpdateObjectExpression,\n} from '../parser/update-set-parser.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\nimport { OnDuplicateKeyNode } from '../operation-node/on-duplicate-key-node.js'\nimport { InsertResult } from './insert-result.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport type {\n  ReturningAllRow,\n  ReturningCallbackRow,\n  ReturningRow,\n} from '../parser/returning-parser.js'\nimport {\n  isNoResultErrorConstructor,\n  NoResultError,\n  type NoResultErrorConstructor,\n} from './no-result-error.js'\nimport {\n  type ExpressionOrFactory,\n  parseExpression,\n} from '../parser/expression-parser.js'\nimport { ColumnNode } from '../operation-node/column-node.js'\nimport type { ReturningInterface } from './returning-interface.js'\nimport {\n  OnConflictBuilder,\n  type OnConflictDatabase,\n  type OnConflictDoNothingBuilder,\n  type OnConflictTables,\n  type OnConflictUpdateBuilder,\n} from './on-conflict-builder.js'\nimport { OnConflictNode } from '../operation-node/on-conflict-node.js'\nimport type { Selectable } from '../util/column-type.js'\nimport type { Explainable, ExplainFormat } from '../util/explainable.js'\nimport type { Expression } from '../expression/expression.js'\nimport type { KyselyTypeError } from '../util/type-error.js'\nimport type { Streamable } from '../util/streamable.js'\nimport { parseTop } from '../parser/top-parser.js'\nimport type {\n  OutputCallback,\n  OutputExpression,\n  OutputInterface,\n  SelectExpressionFromOutputCallback,\n  SelectExpressionFromOutputExpression,\n} from './output-interface.js'\nimport { OrActionNode } from '../operation-node/or-action-node.js'\n\nexport class InsertQueryBuilder<DB, TB extends keyof DB, O>\n  implements\n    ReturningInterface<DB, TB, O>,\n    OutputInterface<DB, TB, O, 'inserted'>,\n    OperationNodeSource,\n    Compilable<O>,\n    Explainable,\n    Streamable<O>\n{\n  readonly #props: InsertQueryBuilderProps\n\n  constructor(props: InsertQueryBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Sets the values to insert for an {@link Kysely.insertInto | insert} query.\n   *\n   * This method takes an object whose keys are column names and values are\n   * values to insert. In addition to the column's type, the values can be\n   * raw {@link sql} snippets or select queries.\n   *\n   * You must provide all fields you haven't explicitly marked as nullable\n   * or optional using {@link Generated} or {@link ColumnType}.\n   *\n   * The return value of an `insert` query is an instance of {@link InsertResult}. The\n   * {@link InsertResult.insertId | insertId} field holds the auto incremented primary\n   * key if the database returned one.\n   *\n   * On PostgreSQL and some other dialects, you need to call `returning` to get\n   * something out of the query.\n   *\n   * Also see the {@link expression} method for inserting the result of a select\n   * query or any other expression.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"insert\", \"Single row\", 10) -->\n   *\n   * Insert a single row:\n   *\n   * ```ts\n   * const result = await db\n   *   .insertInto('person')\n   *   .values({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston',\n   *     age: 40\n   *   })\n   *   .executeTakeFirst()\n   *\n   * // `insertId` is only available on dialects that\n   * // automatically return the id of the inserted row\n   * // such as MySQL and SQLite. On PostgreSQL, for example,\n   * // you need to add a `returning` clause to the query to\n   * // get anything out. See the \"returning data\" example.\n   * console.log(result.insertId)\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * insert into `person` (`first_name`, `last_name`, `age`) values (?, ?, ?)\n   * ```\n   *\n   * <!-- siteExample(\"insert\", \"Multiple rows\", 20) -->\n   *\n   * On dialects that support it (for example PostgreSQL) you can insert multiple\n   * rows by providing an array. Note that the return value is once again very\n   * dialect-specific. Some databases may only return the id of the *last* inserted\n   * row and some return nothing at all unless you call `returning`.\n   *\n   * ```ts\n   * await db\n   *   .insertInto('person')\n   *   .values([{\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston',\n   *     age: 40,\n   *   }, {\n   *     first_name: 'Arnold',\n   *     last_name: 'Schwarzenegger',\n   *     age: 70,\n   *   }])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"last_name\", \"age\") values (($1, $2, $3), ($4, $5, $6))\n   * ```\n   *\n   * <!-- siteExample(\"insert\", \"Returning data\", 30) -->\n   *\n   * On supported dialects like PostgreSQL you need to chain `returning` to the query to get\n   * the inserted row's columns (or any other expression) as the return value. `returning`\n   * works just like `select`. Refer to `select` method's examples and documentation for\n   * more info.\n   *\n   * ```ts\n   * const result = await db\n   *   .insertInto('person')\n   *   .values({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston',\n   *     age: 40,\n   *   })\n   *   .returning(['id', 'first_name as name'])\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"last_name\", \"age\") values ($1, $2, $3) returning \"id\", \"first_name\" as \"name\"\n   * ```\n   *\n   * <!-- siteExample(\"insert\", \"Complex values\", 40) -->\n   *\n   * In addition to primitives, the values can also be arbitrary expressions.\n   * You can build the expressions by using a callback and calling the methods\n   * on the expression builder passed to it:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const ani = \"Ani\"\n   * const ston = \"ston\"\n   *\n   * const result = await db\n   *   .insertInto('person')\n   *   .values(({ ref, selectFrom, fn }) => ({\n   *     first_name: 'Jennifer',\n   *     last_name: sql<string>`concat(${ani}, ${ston})`,\n   *     middle_name: ref('first_name'),\n   *     age: selectFrom('person')\n   *       .select(fn.avg<number>('age').as('avg_age')),\n   *   }))\n   *   .executeTakeFirst()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\n   *   \"first_name\",\n   *   \"last_name\",\n   *   \"middle_name\",\n   *   \"age\"\n   * )\n   * values (\n   *   $1,\n   *   concat($2, $3),\n   *   \"first_name\",\n   *   (select avg(\"age\") as \"avg_age\" from \"person\")\n   * )\n   * ```\n   *\n   * You can also use the callback version of subqueries or raw expressions:\n   *\n   * ```ts\n   * await db.with('jennifer', (db) => db\n   *   .selectFrom('person')\n   *   .where('first_name', '=', 'Jennifer')\n   *   .select(['id', 'first_name', 'gender'])\n   *   .limit(1)\n   * ).insertInto('pet').values((eb) => ({\n   *   owner_id: eb.selectFrom('jennifer').select('id'),\n   *   name: eb.selectFrom('jennifer').select('first_name'),\n   *   species: 'cat',\n   * }))\n   * .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * with \"jennifer\" as (\n   *   select \"id\", \"first_name\", \"gender\"\n   *   from \"person\"\n   *   where \"first_name\" = $1\n   *   limit $2\n   * )\n   * insert into \"pet\" (\"owner_id\", \"name\", \"species\")\n   * values (\n   *  (select \"id\" from \"jennifer\"),\n   *  (select \"first_name\" from \"jennifer\"),\n   *  $3\n   * )\n   * ```\n   */\n  values(insert: InsertExpression<DB, TB>): InsertQueryBuilder<DB, TB, O> {\n    const [columns, values] = parseInsertExpression(insert)\n\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        columns,\n        values,\n      }),\n    })\n  }\n\n  /**\n   * Sets the columns to insert.\n   *\n   * The {@link values} method sets both the columns and the values and this method\n   * is not needed. But if you are using the {@link expression} method, you can use\n   * this method to set the columns to insert.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .columns(['first_name'])\n   *   .expression((eb) => eb.selectFrom('pet').select('pet.name'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\")\n   * select \"pet\".\"name\" from \"pet\"\n   * ```\n   */\n  columns(\n    columns: ReadonlyArray<keyof DB[TB] & string>,\n  ): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        columns: freeze(columns.map(ColumnNode.create)),\n      }),\n    })\n  }\n\n  /**\n   * Insert an arbitrary expression. For example the result of a select query.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"insert\", \"Insert subquery\", 50) -->\n   *\n   * You can create an `INSERT INTO SELECT FROM` query using the `expression` method.\n   * This API doesn't follow our WYSIWYG principles and might be a bit difficult to\n   * remember. The reasons for this design stem from implementation difficulties.\n   *\n   * ```ts\n   * const result = await db.insertInto('person')\n   *   .columns(['first_name', 'last_name', 'age'])\n   *   .expression((eb) => eb\n   *     .selectFrom('pet')\n   *     .select((eb) => [\n   *       'pet.name',\n   *       eb.val('Petson').as('last_name'),\n   *       eb.lit(7).as('age'),\n   *     ])\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"last_name\", \"age\")\n   * select \"pet\".\"name\", $1 as \"last_name\", 7 as \"age from \"pet\"\n   * ```\n   */\n  expression(\n    expression: ExpressionOrFactory<DB, TB, any>,\n  ): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        values: parseExpression(expression),\n      }),\n    })\n  }\n\n  /**\n   * Creates an `insert into \"person\" default values` query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .defaultValues()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" default values\n   * ```\n   */\n  defaultValues(): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        defaultValues: true,\n      }),\n    })\n  }\n\n  /**\n   * This can be used to add any additional SQL to the end of the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.insertInto('person')\n   *   .values({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'male',\n   *   })\n   *   .modifyEnd(sql`-- This is a comment`)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * insert into `person` (\"first_name\", \"last_name\", \"gender\")\n   * values (?, ?, ?) -- This is a comment\n   * ```\n   */\n  modifyEnd(modifier: Expression<any>): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        modifier.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Changes an `insert into` query to an `insert ignore into` query.\n   *\n   * This is only supported by some dialects like MySQL.\n   *\n   * To avoid a footgun, when invoked with the SQLite dialect, this method will\n   * be handled like {@link orIgnore}. See also, {@link orAbort}, {@link orFail},\n   * {@link orReplace}, and {@link orRollback}.\n   *\n   * If you use the ignore modifier, ignorable errors that occur while executing the\n   * insert statement are ignored. For example, without ignore, a row that duplicates\n   * an existing unique index or primary key value in the table causes a duplicate-key\n   * error and the statement is aborted. With ignore, the row is discarded and no error\n   * occurs.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .ignore()\n   *   .values({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'female',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * insert ignore into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)\n   * ```\n   *\n   * The generated SQL (SQLite):\n   *\n   * ```sql\n   * insert or ignore into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)\n   * ```\n   */\n  ignore(): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        orAction: OrActionNode.create('ignore'),\n      }),\n    })\n  }\n\n  /**\n   * Changes an `insert into` query to an `insert or ignore into` query.\n   *\n   * This is only supported by some dialects like SQLite.\n   *\n   * To avoid a footgun, when invoked with the MySQL dialect, this method will\n   * be handled like {@link ignore}.\n   *\n   * See also, {@link orAbort}, {@link orFail}, {@link orReplace}, and {@link orRollback}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .orIgnore()\n   *   .values({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'female',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (SQLite):\n   *\n   * ```sql\n   * insert or ignore into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * insert ignore into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)\n   * ```\n   */\n  orIgnore(): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        orAction: OrActionNode.create('ignore'),\n      }),\n    })\n  }\n\n  /**\n   * Changes an `insert into` query to an `insert or abort into` query.\n   *\n   * This is only supported by some dialects like SQLite.\n   *\n   * See also, {@link orIgnore}, {@link orFail}, {@link orReplace}, and {@link orRollback}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .orAbort()\n   *   .values({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'female',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (SQLite):\n   *\n   * ```sql\n   * insert or abort into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)\n   * ```\n   */\n  orAbort(): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        orAction: OrActionNode.create('abort'),\n      }),\n    })\n  }\n\n  /**\n   * Changes an `insert into` query to an `insert or fail into` query.\n   *\n   * This is only supported by some dialects like SQLite.\n   *\n   * See also, {@link orIgnore}, {@link orAbort}, {@link orReplace}, and {@link orRollback}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .orFail()\n   *   .values({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'female',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (SQLite):\n   *\n   * ```sql\n   * insert or fail into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)\n   * ```\n   */\n  orFail(): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        orAction: OrActionNode.create('fail'),\n      }),\n    })\n  }\n\n  /**\n   * Changes an `insert into` query to an `insert or replace into` query.\n   *\n   * This is only supported by some dialects like SQLite.\n   *\n   * You can also use {@link Kysely.replaceInto} to achieve the same result.\n   *\n   * See also, {@link orIgnore}, {@link orAbort}, {@link orFail}, and {@link orRollback}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .orReplace()\n   *   .values({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'female',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (SQLite):\n   *\n   * ```sql\n   * insert or replace into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)\n   * ```\n   */\n  orReplace(): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        orAction: OrActionNode.create('replace'),\n      }),\n    })\n  }\n\n  /**\n   * Changes an `insert into` query to an `insert or rollback into` query.\n   *\n   * This is only supported by some dialects like SQLite.\n   *\n   * See also, {@link orIgnore}, {@link orAbort}, {@link orFail}, and {@link orReplace}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .orRollback()\n   *   .values({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'female',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (SQLite):\n   *\n   * ```sql\n   * insert or rollback into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)\n   * ```\n   */\n  orRollback(): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        orAction: OrActionNode.create('rollback'),\n      }),\n    })\n  }\n\n  /**\n   * Changes an `insert into` query to an `insert top into` query.\n   *\n   * `top` clause is only supported by some dialects like MS SQL Server.\n   *\n   * ### Examples\n   *\n   * Insert the first 5 rows:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.insertInto('person')\n   *   .top(5)\n   *   .columns(['first_name', 'gender'])\n   *   .expression(\n   *     (eb) => eb.selectFrom('pet').select(['name', sql.lit('other').as('gender')])\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * insert top(5) into \"person\" (\"first_name\", \"gender\") select \"name\", 'other' as \"gender\" from \"pet\"\n   * ```\n   *\n   * Insert the first 50 percent of rows:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.insertInto('person')\n   *   .top(50, 'percent')\n   *   .columns(['first_name', 'gender'])\n   *   .expression(\n   *     (eb) => eb.selectFrom('pet').select(['name', sql.lit('other').as('gender')])\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * insert top(50) percent into \"person\" (\"first_name\", \"gender\") select \"name\", 'other' as \"gender\" from \"pet\"\n   * ```\n   */\n  top(\n    expression: number | bigint,\n    modifiers?: 'percent',\n  ): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithTop(\n        this.#props.queryNode,\n        parseTop(expression, modifiers),\n      ),\n    })\n  }\n\n  /**\n   * Adds an `on conflict` clause to the query.\n   *\n   * `on conflict` is only supported by some dialects like PostgreSQL and SQLite. On MySQL\n   * you can use {@link ignore} and {@link onDuplicateKeyUpdate} to achieve similar results.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db\n   *   .insertInto('pet')\n   *   .values({\n   *     name: 'Catto',\n   *     species: 'cat',\n   *     owner_id: 3,\n   *   })\n   *   .onConflict((oc) => oc\n   *     .column('name')\n   *     .doUpdateSet({ species: 'hamster' })\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"pet\" (\"name\", \"species\", \"owner_id\")\n   * values ($1, $2, $3)\n   * on conflict (\"name\")\n   * do update set \"species\" = $4\n   * ```\n   *\n   * You can provide the name of the constraint instead of a column name:\n   *\n   * ```ts\n   * await db\n   *   .insertInto('pet')\n   *   .values({\n   *     name: 'Catto',\n   *     species: 'cat',\n   *     owner_id: 3,\n   *   })\n   *   .onConflict((oc) => oc\n   *     .constraint('pet_name_key')\n   *     .doUpdateSet({ species: 'hamster' })\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"pet\" (\"name\", \"species\", \"owner_id\")\n   * values ($1, $2, $3)\n   * on conflict on constraint \"pet_name_key\"\n   * do update set \"species\" = $4\n   * ```\n   *\n   * You can also specify an expression as the conflict target in case\n   * the unique index is an expression index:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db\n   *   .insertInto('pet')\n   *   .values({\n   *     name: 'Catto',\n   *     species: 'cat',\n   *     owner_id: 3,\n   *   })\n   *   .onConflict((oc) => oc\n   *     .expression(sql<string>`lower(name)`)\n   *     .doUpdateSet({ species: 'hamster' })\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"pet\" (\"name\", \"species\", \"owner_id\")\n   * values ($1, $2, $3)\n   * on conflict (lower(name))\n   * do update set \"species\" = $4\n   * ```\n   *\n   * You can add a filter for the update statement like this:\n   *\n   * ```ts\n   * await db\n   *   .insertInto('pet')\n   *   .values({\n   *     name: 'Catto',\n   *     species: 'cat',\n   *     owner_id: 3,\n   *   })\n   *   .onConflict((oc) => oc\n   *     .column('name')\n   *     .doUpdateSet({ species: 'hamster' })\n   *     .where('excluded.name', '!=', 'Catto')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"pet\" (\"name\", \"species\", \"owner_id\")\n   * values ($1, $2, $3)\n   * on conflict (\"name\")\n   * do update set \"species\" = $4\n   * where \"excluded\".\"name\" != $5\n   * ```\n   *\n   * You can create an `on conflict do nothing` clauses like this:\n   *\n   * ```ts\n   * await db\n   *   .insertInto('pet')\n   *   .values({\n   *     name: 'Catto',\n   *     species: 'cat',\n   *     owner_id: 3,\n   *   })\n   *   .onConflict((oc) => oc\n   *     .column('name')\n   *     .doNothing()\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"pet\" (\"name\", \"species\", \"owner_id\")\n   * values ($1, $2, $3)\n   * on conflict (\"name\") do nothing\n   * ```\n   *\n   * You can refer to the columns of the virtual `excluded` table\n   * in a type-safe way using a callback and the `ref` method of\n   * `ExpressionBuilder`:\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .values({\n   *     id: 1,\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'male',\n   *   })\n   *   .onConflict(oc => oc\n   *     .column('id')\n   *     .doUpdateSet({\n   *       first_name: (eb) => eb.ref('excluded.first_name'),\n   *       last_name: (eb) => eb.ref('excluded.last_name')\n   *     })\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"id\", \"first_name\", \"last_name\", \"gender\")\n   * values ($1, $2, $3, $4)\n   * on conflict (\"id\")\n   * do update set\n   *  \"first_name\" = \"excluded\".\"first_name\",\n   *  \"last_name\" = \"excluded\".\"last_name\"\n   * ```\n   */\n  onConflict(\n    callback: (\n      builder: OnConflictBuilder<DB, TB>,\n    ) =>\n      | OnConflictUpdateBuilder<\n          OnConflictDatabase<DB, TB>,\n          OnConflictTables<TB>\n        >\n      | OnConflictDoNothingBuilder<DB, TB>,\n  ): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        onConflict: callback(\n          new OnConflictBuilder({\n            onConflictNode: OnConflictNode.create(),\n          }),\n        ).toOperationNode(),\n      }),\n    })\n  }\n\n  /**\n   * Adds `on duplicate key update` to the query.\n   *\n   * If you specify `on duplicate key update`, and a row is inserted that would cause\n   * a duplicate value in a unique index or primary key, an update of the old row occurs.\n   *\n   * This is only implemented by some dialects like MySQL. On most dialects you should\n   * use {@link onConflict} instead.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db\n   *   .insertInto('person')\n   *   .values({\n   *     id: 1,\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'male',\n   *   })\n   *   .onDuplicateKeyUpdate({ updated_at: new Date().toISOString() })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * insert into `person` (`id`, `first_name`, `last_name`, `gender`)\n   * values (?, ?, ?, ?)\n   * on duplicate key update `updated_at` = ?\n   * ```\n   */\n  onDuplicateKeyUpdate(\n    update: UpdateObjectExpression<DB, TB, TB>,\n  ): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {\n        onDuplicateKey: OnDuplicateKeyNode.create(\n          parseUpdateObjectExpression(update),\n        ),\n      }),\n    })\n  }\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selections: ReadonlyArray<SE>,\n  ): InsertQueryBuilder<DB, TB, ReturningRow<DB, TB, O, SE>>\n\n  returning<CB extends SelectCallback<DB, TB>>(\n    callback: CB,\n  ): InsertQueryBuilder<DB, TB, ReturningCallbackRow<DB, TB, O, CB>>\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selection: SE,\n  ): InsertQueryBuilder<DB, TB, ReturningRow<DB, TB, O, SE>>\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selection: SelectArg<DB, TB, SE>,\n  ): InsertQueryBuilder<DB, TB, ReturningRow<DB, TB, O, SE>> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectArg(selection),\n      ),\n    })\n  }\n\n  returningAll(): InsertQueryBuilder<DB, TB, Selectable<DB[TB]>> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectAll(),\n      ),\n    })\n  }\n\n  output<OE extends OutputExpression<DB, TB, 'inserted'>>(\n    selections: readonly OE[],\n  ): InsertQueryBuilder<\n    DB,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output<CB extends OutputCallback<DB, TB, 'inserted'>>(\n    callback: CB,\n  ): InsertQueryBuilder<\n    DB,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputCallback<CB>>\n  >\n\n  output<OE extends OutputExpression<DB, TB, 'inserted'>>(\n    selection: OE,\n  ): InsertQueryBuilder<\n    DB,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output(args: any): any {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectArg(args),\n      ),\n    })\n  }\n\n  outputAll(\n    table: 'inserted',\n  ): InsertQueryBuilder<DB, TB, ReturningAllRow<DB, TB, O>> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n\n  /**\n   * Clears all `returning` clauses from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.insertInto('person')\n   *   .values({ first_name: 'James', last_name: 'Smith', gender: 'male' })\n   *   .returning(['first_name'])\n   *   .clearReturning()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)\n   * ```\n   */\n  clearReturning(): InsertQueryBuilder<DB, TB, InsertResult> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithoutReturning(this.#props.queryNode),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   *\n   * If you want to conditionally call a method on `this`, see\n   * the {@link $if} method.\n   *\n   * ### Examples\n   *\n   * The next example uses a helper function `log` to log a query:\n   *\n   * ```ts\n   * import type { Compilable } from 'kysely'\n   *\n   * function log<T extends Compilable>(qb: T): T {\n   *   console.log(qb.compile())\n   *   return qb\n   * }\n   *\n   * await db.insertInto('person')\n   *   .values({ first_name: 'John', last_name: 'Doe', gender: 'male' })\n   *   .$call(log)\n   *   .execute()\n   * ```\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  /**\n   * Call `func(this)` if `condition` is true.\n   *\n   * This method is especially handy with optional selects. Any `returning` or `returningAll`\n   * method calls add columns as optional fields to the output type when called inside\n   * the `func` callback. This is because we can't know if those selections were actually\n   * made before running the code.\n   *\n   * You can also call any other methods inside the callback.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { NewPerson } from 'type-editor' // imaginary module\n   *\n   * async function insertPerson(values: NewPerson, returnLastName: boolean) {\n   *   return await db\n   *     .insertInto('person')\n   *     .values(values)\n   *     .returning(['id', 'first_name'])\n   *     .$if(returnLastName, (qb) => qb.returning('last_name'))\n   *     .executeTakeFirstOrThrow()\n   * }\n   * ```\n   *\n   * Any selections added inside the `if` callback will be added as optional fields to the\n   * output type since we can't know if the selections were actually made before running\n   * the code. In the example above the return type of the `insertPerson` function is:\n   *\n   * ```ts\n   * Promise<{\n   *   id: number\n   *   first_name: string\n   *   last_name?: string\n   * }>\n   * ```\n   */\n  $if<O2>(\n    condition: boolean,\n    func: (qb: this) => InsertQueryBuilder<any, any, O2>,\n  ): O2 extends InsertResult\n    ? InsertQueryBuilder<DB, TB, InsertResult>\n    : O2 extends O & infer E\n      ? InsertQueryBuilder<DB, TB, O & Partial<E>>\n      : InsertQueryBuilder<DB, TB, Partial<O2>> {\n    if (condition) {\n      return func(this) as any\n    }\n\n    return new InsertQueryBuilder({\n      ...this.#props,\n    }) as any\n  }\n\n  /**\n   * Change the output type of the query.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `InsertQueryBuilder` with a new output type.\n   */\n  $castTo<C>(): InsertQueryBuilder<DB, TB, C> {\n    return new InsertQueryBuilder(this.#props)\n  }\n\n  /**\n   * Narrows (parts of) the output type of the query.\n   *\n   * Kysely tries to be as type-safe as possible, but in some cases we have to make\n   * compromises for better maintainability and compilation performance. At present,\n   * Kysely doesn't narrow the output type of the query based on {@link values} input\n   * when using {@link returning} or {@link returningAll}.\n   *\n   * This utility method is very useful for these situations, as it removes unncessary\n   * runtime assertion/guard code. Its input type is limited to the output type\n   * of the query, so you can't add a column that doesn't exist, or change a column's\n   * type to something that doesn't exist in its union type.\n   *\n   * ### Examples\n   *\n   * Turn this code:\n   *\n   * ```ts\n   * import type { Person } from 'type-editor' // imaginary module\n   *\n   * const person = await db.insertInto('person')\n   *   .values({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'male',\n   *     nullable_column: 'hell yeah!'\n   *   })\n   *   .returningAll()\n   *   .executeTakeFirstOrThrow()\n   *\n   * if (isWithNoNullValue(person)) {\n   *   functionThatExpectsPersonWithNonNullValue(person)\n   * }\n   *\n   * function isWithNoNullValue(person: Person): person is Person & { nullable_column: string } {\n   *   return person.nullable_column != null\n   * }\n   * ```\n   *\n   * Into this:\n   *\n   * ```ts\n   * import type { NotNull } from 'kysely'\n   *\n   * const person = await db.insertInto('person')\n   *   .values({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'male',\n   *     nullable_column: 'hell yeah!'\n   *   })\n   *   .returningAll()\n   *   .$narrowType<{ nullable_column: NotNull }>()\n   *   .executeTakeFirstOrThrow()\n   *\n   * functionThatExpectsPersonWithNonNullValue(person)\n   * ```\n   */\n  $narrowType<T>(): InsertQueryBuilder<DB, TB, NarrowPartial<O, T>> {\n    return new InsertQueryBuilder(this.#props)\n  }\n\n  /**\n   * Asserts that query's output row type equals the given type `T`.\n   *\n   * This method can be used to simplify excessively complex types to make TypeScript happy\n   * and much faster.\n   *\n   * Kysely uses complex type magic to achieve its type safety. This complexity is sometimes too much\n   * for TypeScript and you get errors like this:\n   *\n   * ```\n   * error TS2589: Type instantiation is excessively deep and possibly infinite.\n   * ```\n   *\n   * In these case you can often use this method to help TypeScript a little bit. When you use this\n   * method to assert the output type of a query, Kysely can drop the complex output type that\n   * consists of multiple nested helper types and replace it with the simple asserted type.\n   *\n   * Using this method doesn't reduce type safety at all. You have to pass in a type that is\n   * structurally equal to the current type.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { NewPerson, NewPet, Species } from 'type-editor' // imaginary module\n   *\n   * async function insertPersonAndPet(person: NewPerson, pet: Omit<NewPet, 'owner_id'>) {\n   *   return await db\n   *     .with('new_person', (qb) => qb\n   *       .insertInto('person')\n   *       .values(person)\n   *       .returning('id')\n   *       .$assertType<{ id: number }>()\n   *     )\n   *     .with('new_pet', (qb) => qb\n   *       .insertInto('pet')\n   *       .values((eb) => ({\n   *         owner_id: eb.selectFrom('new_person').select('id'),\n   *         ...pet\n   *       }))\n   *       .returning(['name as pet_name', 'species'])\n   *       .$assertType<{ pet_name: string, species: Species }>()\n   *     )\n   *     .selectFrom(['new_person', 'new_pet'])\n   *     .selectAll()\n   *     .executeTakeFirstOrThrow()\n   * }\n   * ```\n   */\n  $assertType<T extends O>(): O extends T\n    ? InsertQueryBuilder<DB, TB, T>\n    : KyselyTypeError<`$assertType() call failed: The type passed in is not equal to the output type of the query.`> {\n    return new InsertQueryBuilder(this.#props) as unknown as any\n  }\n\n  /**\n   * Returns a copy of this InsertQueryBuilder instance with the given plugin installed.\n   */\n  withPlugin(plugin: KyselyPlugin): InsertQueryBuilder<DB, TB, O> {\n    return new InsertQueryBuilder({\n      ...this.#props,\n      executor: this.#props.executor.withPlugin(plugin),\n    })\n  }\n\n  toOperationNode(): InsertQueryNode {\n    return this.#props.executor.transformQuery(\n      this.#props.queryNode,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery<O> {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  /**\n   * Executes the query and returns an array of rows.\n   *\n   * Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.\n   */\n  async execute(): Promise<SimplifyResult<O>[]> {\n    const compiledQuery = this.compile()\n\n    const result = await this.#props.executor.executeQuery<O>(compiledQuery)\n\n    const { adapter } = this.#props.executor\n    const query = compiledQuery.query as InsertQueryNode\n\n    if (\n      (query.returning && adapter.supportsReturning) ||\n      (query.output && adapter.supportsOutput)\n    ) {\n      return result.rows as any\n    }\n\n    return [\n      new InsertResult(\n        result.insertId,\n        result.numAffectedRows ?? BigInt(0),\n      ) as any,\n    ]\n  }\n\n  /**\n   * Executes the query and returns the first result or undefined if\n   * the query returned no result.\n   */\n  async executeTakeFirst(): Promise<SimplifySingleResult<O>> {\n    const [result] = await this.execute()\n    return result as SimplifySingleResult<O>\n  }\n\n  /**\n   * Executes the query and returns the first result or throws if\n   * the query returned no result.\n   *\n   * By default an instance of {@link NoResultError} is thrown, but you can\n   * provide a custom error class, or callback as the only argument to throw a different\n   * error.\n   */\n  async executeTakeFirstOrThrow(\n    errorConstructor:\n      | NoResultErrorConstructor\n      | ((node: QueryNode) => Error) = NoResultError,\n  ): Promise<SimplifyResult<O>> {\n    const result = await this.executeTakeFirst()\n\n    if (result === undefined) {\n      const error = isNoResultErrorConstructor(errorConstructor)\n        ? new errorConstructor(this.toOperationNode())\n        : errorConstructor(this.toOperationNode())\n\n      throw error\n    }\n\n    return result as SimplifyResult<O>\n  }\n\n  async *stream(chunkSize: number = 100): AsyncIterableIterator<O> {\n    const compiledQuery = this.compile()\n\n    const stream = this.#props.executor.stream<O>(compiledQuery, chunkSize)\n\n    for await (const item of stream) {\n      yield* item.rows\n    }\n  }\n\n  async explain<ER extends Record<string, any> = Record<string, any>>(\n    format?: ExplainFormat,\n    options?: Expression<any>,\n  ): Promise<ER[]> {\n    const builder = new InsertQueryBuilder<DB, TB, ER>({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithExplain(\n        this.#props.queryNode,\n        format,\n        options,\n      ),\n    })\n\n    return await builder.execute()\n  }\n}\n\nexport interface InsertQueryBuilderProps {\n  readonly queryId: QueryId\n  readonly queryNode: InsertQueryNode\n  readonly executor: QueryExecutor\n}\n"
  },
  {
    "path": "src/query-builder/insert-result.ts",
    "content": "/**\n * The result of an insert query.\n *\n * If the table has an auto incrementing primary key {@link insertId} will hold\n * the generated id on dialects that support it. For example PostgreSQL doesn't\n * return the id by default and {@link insertId} is undefined. On PostgreSQL you\n * need to use {@link ReturningInterface.returning} or {@link ReturningInterface.returningAll}\n * to get out the inserted id.\n *\n * {@link numInsertedOrUpdatedRows} holds the number of (actually) inserted rows.\n * On MySQL, updated rows are counted twice when using `on duplicate key update`.\n *\n * ### Examples\n *\n * ```ts\n * import type { NewPerson } from 'type-editor' // imaginary module\n *\n * async function insertPerson(person: NewPerson) {\n *   const result = await db\n *     .insertInto('person')\n *     .values(person)\n *     .executeTakeFirstOrThrow()\n *\n *   console.log(result.insertId) // relevant on MySQL\n *   console.log(result.numInsertedOrUpdatedRows) // always relevant\n * }\n * ```\n */\nexport class InsertResult {\n  /**\n   * The auto incrementing primary key of the inserted row.\n   *\n   * This property can be undefined when the query contains an `on conflict`\n   * clause that makes the query succeed even when nothing gets inserted.\n   *\n   * This property is always undefined on dialects like PostgreSQL that\n   * don't return the inserted id by default. On those dialects you need\n   * to use the {@link ReturningInterface.returning | returning} method.\n   */\n  readonly insertId: bigint | undefined\n\n  /**\n   * Affected rows count.\n   */\n  readonly numInsertedOrUpdatedRows: bigint | undefined\n\n  constructor(\n    insertId: bigint | undefined,\n    numInsertedOrUpdatedRows: bigint | undefined,\n  ) {\n    this.insertId = insertId\n    this.numInsertedOrUpdatedRows = numInsertedOrUpdatedRows\n  }\n}\n"
  },
  {
    "path": "src/query-builder/join-builder.ts",
    "content": "import { JoinNode } from '../operation-node/join-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { RawNode } from '../operation-node/raw-node.js'\nimport {\n  type ComparisonOperatorExpression,\n  type OperandValueExpressionOrList,\n  parseValueBinaryOperationOrExpression,\n  parseReferentialBinaryOperation,\n} from '../parser/binary-operation-parser.js'\nimport type { ExpressionOrFactory } from '../parser/expression-parser.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { SqlBool } from '../util/type-utils.js'\n\nexport class JoinBuilder<\n  DB,\n  TB extends keyof DB,\n> implements OperationNodeSource {\n  readonly #props: JoinBuilderProps\n\n  constructor(props: JoinBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Just like {@link WhereInterface.where} but adds an item to the join's\n   * `on` clause instead.\n   *\n   * See {@link WhereInterface.where} for documentation and examples.\n   */\n  on<RE extends ReferenceExpression<DB, TB>>(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: OperandValueExpressionOrList<DB, TB, RE>,\n  ): JoinBuilder<DB, TB>\n\n  on(expression: ExpressionOrFactory<DB, TB, SqlBool>): JoinBuilder<DB, TB>\n\n  on(...args: any[]): JoinBuilder<DB, TB> {\n    return new JoinBuilder({\n      ...this.#props,\n      joinNode: JoinNode.cloneWithOn(\n        this.#props.joinNode,\n        parseValueBinaryOperationOrExpression(args),\n      ),\n    })\n  }\n\n  /**\n   * Just like {@link WhereInterface.whereRef} but adds an item to the join's\n   * `on` clause instead.\n   *\n   * See {@link WhereInterface.whereRef} for documentation and examples.\n   */\n  onRef(\n    lhs: ReferenceExpression<DB, TB>,\n    op: ComparisonOperatorExpression,\n    rhs: ReferenceExpression<DB, TB>,\n  ): JoinBuilder<DB, TB> {\n    return new JoinBuilder({\n      ...this.#props,\n      joinNode: JoinNode.cloneWithOn(\n        this.#props.joinNode,\n        parseReferentialBinaryOperation(lhs, op, rhs),\n      ),\n    })\n  }\n\n  /**\n   * Adds `on true`.\n   */\n  onTrue(): JoinBuilder<DB, TB> {\n    return new JoinBuilder({\n      ...this.#props,\n      joinNode: JoinNode.cloneWithOn(\n        this.#props.joinNode,\n        RawNode.createWithSql('true'),\n      ),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): JoinNode {\n    return this.#props.joinNode\n  }\n}\n\nexport interface JoinBuilderProps {\n  readonly joinNode: JoinNode\n}\n"
  },
  {
    "path": "src/query-builder/json-path-builder.ts",
    "content": "import type {\n  AliasableExpression,\n  AliasedExpression,\n  Expression,\n} from '../expression/expression.js'\nimport { AliasNode } from '../operation-node/alias-node.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport { JSONOperatorChainNode } from '../operation-node/json-operator-chain-node.js'\nimport {\n  JSONPathLegNode,\n  type JSONPathLegType,\n} from '../operation-node/json-path-leg-node.js'\nimport { JSONPathNode } from '../operation-node/json-path-node.js'\nimport { JSONReferenceNode } from '../operation-node/json-reference-node.js'\nimport { isOperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport { ValueNode } from '../operation-node/value-node.js'\n\nexport class JSONPathBuilder<S, O = S> {\n  readonly #node: JSONReferenceNode | JSONPathNode\n\n  constructor(node: JSONReferenceNode | JSONPathNode) {\n    this.#node = node\n  }\n\n  /**\n   * Access an element of a JSON array in a specific location.\n   *\n   * Since there's no guarantee an element exists in the given array location, the\n   * resulting type is always nullable. If you're sure the element exists, you\n   * should use {@link SelectQueryBuilder.$assertType} to narrow the type safely.\n   *\n   * See also {@link key} to access properties of JSON objects.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(eb =>\n   *     eb.ref('nicknames', '->').at(0).as('primary_nickname')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"nicknames\"->0 as \"primary_nickname\" from \"person\"\n   *```\n   *\n   * Combined with {@link key}:\n   *\n   * ```ts\n   * db.selectFrom('person').select(eb =>\n   *   eb.ref('experience', '->').at(0).key('role').as('first_role')\n   * )\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"experience\"->0->'role' as \"first_role\" from \"person\"\n   * ```\n   *\n   * You can use `'last'` to access the last element of the array in MySQL:\n   *\n   * ```ts\n   * db.selectFrom('person').select(eb =>\n   *   eb.ref('nicknames', '->$').at('last').as('last_nickname')\n   * )\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * select `nicknames`->'$[last]' as `last_nickname` from `person`\n   * ```\n   *\n   * Or `'#-1'` in SQLite:\n   *\n   * ```ts\n   * db.selectFrom('person').select(eb =>\n   *   eb.ref('nicknames', '->>$').at('#-1').as('last_nickname')\n   * )\n   * ```\n   *\n   * The generated SQL (SQLite):\n   *\n   * ```sql\n   * select \"nicknames\"->>'$[#-1]' as `last_nickname` from `person`\n   * ```\n   */\n  at<\n    I extends any[] extends O ? number | 'last' | `#-${number}` : never,\n    O2 = null | NonNullable<NonNullable<O>[keyof NonNullable<O> & number]>,\n  >(\n    index: `${I}` extends `${any}.${any}` | `#--${any}` ? never : I,\n  ): TraversedJSONPathBuilder<S, O2> {\n    return this.#createBuilderWithPathLeg('ArrayLocation', index)\n  }\n\n  /**\n   * Access a property of a JSON object.\n   *\n   * If a field is optional, the resulting type will be nullable.\n   *\n   * See also {@link at} to access elements of JSON arrays.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * db.selectFrom('person').select(eb =>\n   *   eb.ref('address', '->').key('city').as('city')\n   * )\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"address\"->'city' as \"city\" from \"person\"\n   * ```\n   *\n   * Going deeper:\n   *\n   * ```ts\n   * db.selectFrom('person').select(eb =>\n   *   eb.ref('profile', '->$').key('website').key('url').as('website_url')\n   * )\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * select `profile`->'$.website.url' as `website_url` from `person`\n   * ```\n   *\n   * Combined with {@link at}:\n   *\n   * ```ts\n   * db.selectFrom('person').select(eb =>\n   *   eb.ref('profile', '->').key('addresses').at(0).key('city').as('city')\n   * )\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"profile\"->'addresses'->0->'city' as \"city\" from \"person\"\n   * ```\n   */\n  key<\n    K extends any[] extends O\n      ? never\n      : O extends object\n        ? keyof NonNullable<O> & string\n        : never,\n    O2 = undefined extends O\n      ? null | NonNullable<NonNullable<O>[K]>\n      : null extends O\n        ? null | NonNullable<NonNullable<O>[K]>\n        : // when the object has non-specific keys, e.g. Record<string, T>, should infer `T | null`!\n          string extends keyof NonNullable<O>\n          ? null | NonNullable<NonNullable<O>[K]>\n          : NonNullable<O>[K],\n  >(key: K): TraversedJSONPathBuilder<S, O2> {\n    return this.#createBuilderWithPathLeg('Member', key)\n  }\n\n  #createBuilderWithPathLeg(\n    legType: JSONPathLegType,\n    value: string | number,\n  ): TraversedJSONPathBuilder<any, any> {\n    if (JSONReferenceNode.is(this.#node)) {\n      return new TraversedJSONPathBuilder(\n        JSONReferenceNode.cloneWithTraversal(\n          this.#node,\n          JSONPathNode.is(this.#node.traversal)\n            ? JSONPathNode.cloneWithLeg(\n                this.#node.traversal,\n                JSONPathLegNode.create(legType, value),\n              )\n            : JSONOperatorChainNode.cloneWithValue(\n                this.#node.traversal,\n                ValueNode.createImmediate(value),\n              ),\n        ),\n      )\n    }\n\n    return new TraversedJSONPathBuilder(\n      JSONPathNode.cloneWithLeg(\n        this.#node,\n        JSONPathLegNode.create(legType, value),\n      ),\n    )\n  }\n}\n\nexport class TraversedJSONPathBuilder<S, O>\n  extends JSONPathBuilder<S, O>\n  implements AliasableExpression<O>\n{\n  readonly #node: JSONReferenceNode | JSONPathNode\n\n  constructor(node: JSONReferenceNode | JSONPathNode) {\n    super(node)\n    this.#node = node\n  }\n\n  /** @private */\n  get expressionType(): O | undefined {\n    return undefined\n  }\n\n  /**\n   * Returns an aliased version of the expression.\n   *\n   * In addition to slapping `as \"the_alias\"` to the end of the SQL,\n   * this method also provides strict typing:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select(eb =>\n   *     eb('first_name', '=', 'Jennifer').as('is_jennifer')\n   *   )\n   *   .executeTakeFirstOrThrow()\n   *\n   * // `is_jennifer: SqlBool` field exists in the result type.\n   * console.log(result.is_jennifer)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\" = $1 as \"is_jennifer\"\n   * from \"person\"\n   * ```\n   */\n  as<A extends string>(alias: A): AliasedExpression<O, A>\n  as<A extends string>(alias: Expression<unknown>): AliasedExpression<O, A>\n  as(alias: string | Expression<any>): AliasedExpression<O, string> {\n    return new AliasedJSONPathBuilder(this, alias)\n  }\n\n  /**\n   * Change the output type of the json path.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `JSONPathBuilder` with a new output type.\n   */\n  $castTo<O2>(): TraversedJSONPathBuilder<S, O2> {\n    return new TraversedJSONPathBuilder(this.#node)\n  }\n\n  $notNull(): TraversedJSONPathBuilder<S, Exclude<O, null>> {\n    return new TraversedJSONPathBuilder(this.#node)\n  }\n\n  toOperationNode(): OperationNode {\n    return this.#node\n  }\n}\n\nexport class AliasedJSONPathBuilder<\n  O,\n  A extends string,\n> implements AliasedExpression<O, A> {\n  readonly #jsonPath: TraversedJSONPathBuilder<any, O>\n  readonly #alias: A | Expression<unknown>\n\n  constructor(\n    jsonPath: TraversedJSONPathBuilder<any, O>,\n    alias: A | Expression<unknown>,\n  ) {\n    this.#jsonPath = jsonPath\n    this.#alias = alias\n  }\n\n  /** @private */\n  get expression(): Expression<O> {\n    return this.#jsonPath\n  }\n\n  /** @private */\n  get alias(): A | Expression<unknown> {\n    return this.#alias\n  }\n\n  toOperationNode(): AliasNode {\n    return AliasNode.create(\n      this.#jsonPath.toOperationNode(),\n      isOperationNodeSource(this.#alias)\n        ? this.#alias.toOperationNode()\n        : IdentifierNode.create(this.#alias),\n    )\n  }\n}\n"
  },
  {
    "path": "src/query-builder/merge-query-builder.ts",
    "content": "import type { AliasedExpression, Expression } from '../expression/expression.js'\nimport { InsertQueryNode } from '../operation-node/insert-query-node.js'\nimport { MergeQueryNode } from '../operation-node/merge-query-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { QueryNode } from '../operation-node/query-node.js'\nimport { UpdateQueryNode } from '../operation-node/update-query-node.js'\nimport type {\n  ComparisonOperatorExpression,\n  OperandValueExpressionOrList,\n} from '../parser/binary-operation-parser.js'\nimport type { ExpressionOrFactory } from '../parser/expression-parser.js'\nimport {\n  type InsertExpression,\n  type InsertObjectOrList,\n  type InsertObjectOrListFactory,\n  parseInsertExpression,\n} from '../parser/insert-values-parser.js'\nimport {\n  type JoinCallbackExpression,\n  type JoinReferenceExpression,\n  parseJoin,\n} from '../parser/join-parser.js'\nimport { parseMergeThen, parseMergeWhen } from '../parser/merge-parser.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport type {\n  ReturningAllRow,\n  ReturningCallbackRow,\n  ReturningRow,\n} from '../parser/returning-parser.js'\nimport {\n  parseSelectAll,\n  parseSelectArg,\n  type SelectCallback,\n  type SelectExpression,\n} from '../parser/select-parser.js'\nimport type { TableExpression } from '../parser/table-parser.js'\nimport { parseTop } from '../parser/top-parser.js'\nimport type {\n  ExtractUpdateTypeFromReferenceExpression,\n  UpdateObject,\n  UpdateObjectFactory,\n} from '../parser/update-set-parser.js'\nimport type { ValueExpression } from '../parser/value-parser.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport { NOOP_QUERY_EXECUTOR } from '../query-executor/noop-query-executor.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { Compilable } from '../util/compilable.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { QueryId } from '../util/query-id.js'\nimport type {\n  ShallowRecord,\n  SimplifyResult,\n  SimplifySingleResult,\n  SqlBool,\n} from '../util/type-utils.js'\nimport { MergeResult } from './merge-result.js'\nimport {\n  NoResultError,\n  type NoResultErrorConstructor,\n  isNoResultErrorConstructor,\n} from './no-result-error.js'\nimport type {\n  OutputCallback,\n  OutputExpression,\n  OutputInterface,\n  OutputPrefix,\n  SelectExpressionFromOutputCallback,\n  SelectExpressionFromOutputExpression,\n} from './output-interface.js'\nimport type { MultiTableReturningInterface } from './returning-interface.js'\nimport { UpdateQueryBuilder } from './update-query-builder.js'\n\nexport class MergeQueryBuilder<DB, TT extends keyof DB, O>\n  implements MultiTableReturningInterface<DB, TT, O>, OutputInterface<DB, TT, O>\n{\n  readonly #props: MergeQueryBuilderProps\n\n  constructor(props: MergeQueryBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * This can be used to add any additional SQL to the end of the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db\n   *   .mergeInto('person')\n   *   .using('pet', 'pet.owner_id', 'person.id')\n   *   .whenMatched()\n   *   .thenDelete()\n   *   .modifyEnd(sql.raw('-- this is a comment'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete -- this is a comment\n   * ```\n   */\n  modifyEnd(modifier: Expression<any>): MergeQueryBuilder<DB, TT, O> {\n    return new MergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        modifier.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Changes a `merge into` query to an `merge top into` query.\n   *\n   * `top` clause is only supported by some dialects like MS SQL Server.\n   *\n   * ### Examples\n   *\n   * Affect 5 matched rows at most:\n   *\n   * ```ts\n   * await db.mergeInto('person')\n   *   .top(5)\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenMatched()\n   *   .thenDelete()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * merge top(5) into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when matched then\n   *   delete\n   * ```\n   *\n   * Affect 50% of matched rows:\n   *\n   * ```ts\n   * await db.mergeInto('person')\n   *   .top(50, 'percent')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenMatched()\n   *   .thenDelete()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * merge top(50) percent into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when matched then\n   *   delete\n   * ```\n   */\n  top(\n    expression: number | bigint,\n    modifiers?: 'percent',\n  ): MergeQueryBuilder<DB, TT, O> {\n    return new MergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithTop(\n        this.#props.queryNode,\n        parseTop(expression, modifiers),\n      ),\n    })\n  }\n\n  /**\n   * Adds the `using` clause to the query.\n   *\n   * This method is similar to {@link SelectQueryBuilder.innerJoin}, so see the\n   * documentation for that method for more examples.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenMatched()\n   *   .thenDelete()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when matched then\n   *   delete\n   * ```\n   */\n  using<\n    TE extends TableExpression<DB, TT>,\n    K1 extends JoinReferenceExpression<DB, TT, TE>,\n    K2 extends JoinReferenceExpression<DB, TT, TE>,\n  >(\n    sourceTable: TE,\n    k1: K1,\n    k2: K2,\n  ): ExtractWheneableMergeQueryBuilder<DB, TT, TE, O>\n\n  using<\n    TE extends TableExpression<DB, TT>,\n    FN extends JoinCallbackExpression<DB, TT, TE>,\n  >(\n    sourceTable: TE,\n    callback: FN,\n  ): ExtractWheneableMergeQueryBuilder<DB, TT, TE, O>\n\n  using(...args: any): any {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: MergeQueryNode.cloneWithUsing(\n        this.#props.queryNode,\n        parseJoin('Using', args),\n      ),\n    })\n  }\n\n  returning<SE extends SelectExpression<DB, TT>>(\n    selections: ReadonlyArray<SE>,\n  ): MergeQueryBuilder<DB, TT, ReturningRow<DB, TT, O, SE>>\n\n  returning<CB extends SelectCallback<DB, TT>>(\n    callback: CB,\n  ): MergeQueryBuilder<DB, TT, ReturningCallbackRow<DB, TT, O, CB>>\n\n  returning<SE extends SelectExpression<DB, TT>>(\n    selection: SE,\n  ): MergeQueryBuilder<DB, TT, ReturningRow<DB, TT, O, SE>>\n\n  returning(args: any): any {\n    return new MergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectArg(args),\n      ),\n    })\n  }\n\n  returningAll<T extends TT>(\n    table: T,\n  ): MergeQueryBuilder<DB, TT, ReturningAllRow<DB, T, O>>\n\n  returningAll(): MergeQueryBuilder<DB, TT, ReturningAllRow<DB, TT, O>>\n\n  returningAll(table?: any): any {\n    return new MergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n\n  output<OE extends OutputExpression<DB, TT>>(\n    selections: readonly OE[],\n  ): MergeQueryBuilder<\n    DB,\n    TT,\n    ReturningRow<DB, TT, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output<CB extends OutputCallback<DB, TT>>(\n    callback: CB,\n  ): MergeQueryBuilder<\n    DB,\n    TT,\n    ReturningRow<DB, TT, O, SelectExpressionFromOutputCallback<CB>>\n  >\n\n  output<OE extends OutputExpression<DB, TT>>(\n    selection: OE,\n  ): MergeQueryBuilder<\n    DB,\n    TT,\n    ReturningRow<DB, TT, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output(args: any): any {\n    return new MergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectArg(args),\n      ),\n    })\n  }\n\n  outputAll(\n    table: OutputPrefix,\n  ): MergeQueryBuilder<DB, TT, ReturningAllRow<DB, TT, O>> {\n    return new MergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n}\n\nexport interface MergeQueryBuilderProps {\n  readonly queryId: QueryId\n  readonly queryNode: MergeQueryNode\n  readonly executor: QueryExecutor\n}\n\nexport class WheneableMergeQueryBuilder<\n  DB,\n  TT extends keyof DB,\n  ST extends keyof DB,\n  O,\n>\n  implements\n    Compilable<O>,\n    MultiTableReturningInterface<DB, TT | ST, O>,\n    OutputInterface<DB, TT, O>,\n    OperationNodeSource\n{\n  readonly #props: MergeQueryBuilderProps\n\n  constructor(props: MergeQueryBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * This can be used to add any additional SQL to the end of the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db\n   *   .mergeInto('person')\n   *   .using('pet', 'pet.owner_id', 'person.id')\n   *   .whenMatched()\n   *   .thenDelete()\n   *   .modifyEnd(sql.raw('-- this is a comment'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete -- this is a comment\n   * ```\n   */\n  modifyEnd(\n    modifier: Expression<any>,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, O> {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        modifier.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * See {@link MergeQueryBuilder.top}.\n   */\n  top(\n    expression: number | bigint,\n    modifiers?: 'percent',\n  ): WheneableMergeQueryBuilder<DB, TT, ST, O> {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithTop(\n        this.#props.queryNode,\n        parseTop(expression, modifiers),\n      ),\n    })\n  }\n\n  /**\n   * Adds a simple `when matched` clause to the query.\n   *\n   * For a `when matched` clause with an `and` condition, see {@link whenMatchedAnd}.\n   *\n   * For a simple `when not matched` clause, see {@link whenNotMatched}.\n   *\n   * For a `when not matched` clause with an `and` condition, see {@link whenNotMatchedAnd}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenMatched()\n   *   .thenDelete()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when matched then\n   *   delete\n   * ```\n   */\n  whenMatched(): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT | ST, O> {\n    return this.#whenMatched([])\n  }\n\n  /**\n   * Adds the `when matched` clause to the query with an `and` condition.\n   *\n   * This method is similar to {@link SelectQueryBuilder.where}, so see the documentation\n   * for that method for more examples.\n   *\n   * For a simple `when matched` clause (without an `and` condition) see {@link whenMatched}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenMatchedAnd('person.first_name', '=', 'John')\n   *   .thenDelete()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when matched and \"person\".\"first_name\" = $1 then\n   *   delete\n   * ```\n   */\n  whenMatchedAnd<\n    RE extends ReferenceExpression<DB, TT | ST>,\n    VE extends OperandValueExpressionOrList<DB, TT | ST, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT | ST, O>\n\n  whenMatchedAnd<E extends ExpressionOrFactory<DB, TT | ST, SqlBool>>(\n    expression: E,\n  ): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT | ST, O>\n\n  whenMatchedAnd(\n    ...args: any[]\n  ): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT | ST, O> {\n    return this.#whenMatched(args)\n  }\n\n  /**\n   * Adds the `when matched` clause to the query with an `and` condition. But unlike\n   * {@link whenMatchedAnd}, this method accepts a column reference as the 3rd argument.\n   *\n   * This method is similar to {@link SelectQueryBuilder.whereRef}, so see the documentation\n   * for that method for more examples.\n   */\n  whenMatchedAndRef<\n    LRE extends ReferenceExpression<DB, TT | ST>,\n    RRE extends ReferenceExpression<DB, TT | ST>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT | ST, O> {\n    return this.#whenMatched([lhs, op, rhs], true)\n  }\n\n  #whenMatched(\n    args: any[],\n    refRight?: boolean,\n  ): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT | ST, O> {\n    return new MatchedThenableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: MergeQueryNode.cloneWithWhen(\n        this.#props.queryNode,\n        parseMergeWhen({ isMatched: true }, args, refRight),\n      ),\n    })\n  }\n\n  /**\n   * Adds a simple `when not matched` clause to the query.\n   *\n   * For a `when not matched` clause with an `and` condition, see {@link whenNotMatchedAnd}.\n   *\n   * For a simple `when matched` clause, see {@link whenMatched}.\n   *\n   * For a `when matched` clause with an `and` condition, see {@link whenMatchedAnd}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenNotMatched()\n   *   .thenInsertValues({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when not matched then\n   *   insert (\"first_name\", \"last_name\") values ($1, $2)\n   * ```\n   */\n  whenNotMatched(): NotMatchedThenableMergeQueryBuilder<DB, TT, ST, O> {\n    return this.#whenNotMatched([])\n  }\n\n  /**\n   * Adds the `when not matched` clause to the query with an `and` condition.\n   *\n   * This method is similar to {@link SelectQueryBuilder.where}, so see the documentation\n   * for that method for more examples.\n   *\n   * For a simple `when not matched` clause (without an `and` condition) see {@link whenNotMatched}.\n   *\n   * Unlike {@link whenMatchedAnd}, you cannot reference columns from the table merged into.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenNotMatchedAnd('pet.name', '=', 'Lucky')\n   *   .thenInsertValues({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when not matched and \"pet\".\"name\" = $1 then\n   *   insert (\"first_name\", \"last_name\") values ($2, $3)\n   * ```\n   */\n  whenNotMatchedAnd<\n    RE extends ReferenceExpression<DB, ST>,\n    VE extends OperandValueExpressionOrList<DB, ST, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): NotMatchedThenableMergeQueryBuilder<DB, TT, ST, O>\n\n  whenNotMatchedAnd<E extends ExpressionOrFactory<DB, ST, SqlBool>>(\n    expression: E,\n  ): NotMatchedThenableMergeQueryBuilder<DB, TT, ST, O>\n\n  whenNotMatchedAnd(\n    ...args: any[]\n  ): NotMatchedThenableMergeQueryBuilder<DB, TT, ST, O> {\n    return this.#whenNotMatched(args)\n  }\n\n  /**\n   * Adds the `when not matched` clause to the query with an `and` condition. But unlike\n   * {@link whenNotMatchedAnd}, this method accepts a column reference as the 3rd argument.\n   *\n   * Unlike {@link whenMatchedAndRef}, you cannot reference columns from the target table.\n   *\n   * This method is similar to {@link SelectQueryBuilder.whereRef}, so see the documentation\n   * for that method for more examples.\n   */\n  whenNotMatchedAndRef<\n    LRE extends ReferenceExpression<DB, ST>,\n    RRE extends ReferenceExpression<DB, ST>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): NotMatchedThenableMergeQueryBuilder<DB, TT, ST, O> {\n    return this.#whenNotMatched([lhs, op, rhs], true)\n  }\n\n  /**\n   * Adds a simple `when not matched by source` clause to the query.\n   *\n   * Supported in MS SQL Server.\n   *\n   * Similar to {@link whenNotMatched}, but returns a {@link MatchedThenableMergeQueryBuilder}.\n   */\n  whenNotMatchedBySource(): MatchedThenableMergeQueryBuilder<\n    DB,\n    TT,\n    ST,\n    TT,\n    O\n  > {\n    return this.#whenNotMatched([], false, true)\n  }\n\n  /**\n   * Adds the `when not matched by source` clause to the query with an `and` condition.\n   *\n   * Supported in MS SQL Server.\n   *\n   * Similar to {@link whenNotMatchedAnd}, but returns a {@link MatchedThenableMergeQueryBuilder}.\n   */\n  whenNotMatchedBySourceAnd<\n    RE extends ReferenceExpression<DB, TT>,\n    VE extends OperandValueExpressionOrList<DB, TT, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT, O>\n\n  whenNotMatchedBySourceAnd<E extends ExpressionOrFactory<DB, TT, SqlBool>>(\n    expression: E,\n  ): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT, O>\n\n  whenNotMatchedBySourceAnd(\n    ...args: any[]\n  ): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT, O> {\n    return this.#whenNotMatched(args, false, true)\n  }\n\n  /**\n   * Adds the `when not matched by source` clause to the query with an `and` condition.\n   *\n   * Similar to {@link whenNotMatchedAndRef}, but you can reference columns from\n   * the target table, and not from source table and returns a {@link MatchedThenableMergeQueryBuilder}.\n   */\n  whenNotMatchedBySourceAndRef<\n    LRE extends ReferenceExpression<DB, TT>,\n    RRE extends ReferenceExpression<DB, TT>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): MatchedThenableMergeQueryBuilder<DB, TT, ST, TT, O> {\n    return this.#whenNotMatched([lhs, op, rhs], true, true)\n  }\n\n  returning<SE extends SelectExpression<DB, TT | ST>>(\n    selections: ReadonlyArray<SE>,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, ReturningRow<DB, TT | ST, O, SE>>\n\n  returning<CB extends SelectCallback<DB, TT | ST>>(\n    callback: CB,\n  ): WheneableMergeQueryBuilder<\n    DB,\n    TT,\n    ST,\n    ReturningCallbackRow<DB, TT | ST, O, CB>\n  >\n\n  returning<SE extends SelectExpression<DB, TT | ST>>(\n    selection: SE,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, ReturningRow<DB, TT | ST, O, SE>>\n\n  returning(args: any): any {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectArg(args),\n      ),\n    })\n  }\n\n  returningAll<T extends TT | ST>(\n    table: T,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, ReturningAllRow<DB, T, O>>\n\n  returningAll(): WheneableMergeQueryBuilder<\n    DB,\n    TT,\n    ST,\n    ReturningAllRow<DB, TT | ST, O>\n  >\n\n  returningAll(table?: any): any {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n\n  output<OE extends OutputExpression<DB, TT>>(\n    selections: readonly OE[],\n  ): WheneableMergeQueryBuilder<\n    DB,\n    TT,\n    ST,\n    ReturningRow<DB, TT, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output<CB extends OutputCallback<DB, TT>>(\n    callback: CB,\n  ): WheneableMergeQueryBuilder<\n    DB,\n    TT,\n    ST,\n    ReturningRow<DB, TT, O, SelectExpressionFromOutputCallback<CB>>\n  >\n\n  output<OE extends OutputExpression<DB, TT>>(\n    selection: OE,\n  ): WheneableMergeQueryBuilder<\n    DB,\n    TT,\n    ST,\n    ReturningRow<DB, TT, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output(args: any): any {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectArg(args),\n      ),\n    })\n  }\n\n  outputAll(\n    table: OutputPrefix,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, ReturningAllRow<DB, TT, O>> {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n\n  #whenNotMatched(\n    args: any[],\n    refRight: boolean = false,\n    bySource: boolean = false,\n  ): any {\n    const props: MergeQueryBuilderProps = {\n      ...this.#props,\n      queryNode: MergeQueryNode.cloneWithWhen(\n        this.#props.queryNode,\n        parseMergeWhen({ isMatched: false, bySource }, args, refRight),\n      ),\n    }\n\n    const Builder: any = bySource\n      ? MatchedThenableMergeQueryBuilder\n      : NotMatchedThenableMergeQueryBuilder\n\n    return new Builder(props)\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   *\n   * If you want to conditionally call a method on `this`, see\n   * the {@link $if} method.\n   *\n   * ### Examples\n   *\n   * The next example uses a helper function `log` to log a query:\n   *\n   * ```ts\n   * import type { Compilable } from 'kysely'\n   *\n   * function log<T extends Compilable>(qb: T): T {\n   *   console.log(qb.compile())\n   *   return qb\n   * }\n   *\n   * await db.updateTable('person')\n   *   .set({ first_name: 'John' })\n   *   .$call(log)\n   *   .execute()\n   * ```\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  /**\n   * Call `func(this)` if `condition` is true.\n   *\n   * This method is especially handy with optional selects. Any `returning` or `returningAll`\n   * method calls add columns as optional fields to the output type when called inside\n   * the `func` callback. This is because we can't know if those selections were actually\n   * made before running the code.\n   *\n   * You can also call any other methods inside the callback.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { PersonUpdate } from 'type-editor' // imaginary module\n   *\n   * async function updatePerson(id: number, updates: PersonUpdate, returnLastName: boolean) {\n   *   return await db\n   *     .updateTable('person')\n   *     .set(updates)\n   *     .where('id', '=', id)\n   *     .returning(['id', 'first_name'])\n   *     .$if(returnLastName, (qb) => qb.returning('last_name'))\n   *     .executeTakeFirstOrThrow()\n   * }\n   * ```\n   *\n   * Any selections added inside the `if` callback will be added as optional fields to the\n   * output type since we can't know if the selections were actually made before running\n   * the code. In the example above the return type of the `updatePerson` function is:\n   *\n   * ```ts\n   * Promise<{\n   *   id: number\n   *   first_name: string\n   *   last_name?: string\n   * }>\n   * ```\n   */\n  $if<O2>(\n    condition: boolean,\n    func: (qb: this) => WheneableMergeQueryBuilder<any, any, any, O2>,\n  ): O2 extends MergeResult\n    ? WheneableMergeQueryBuilder<DB, TT, ST, MergeResult>\n    : O2 extends O & infer E\n      ? WheneableMergeQueryBuilder<DB, TT, ST, O & Partial<E>>\n      : WheneableMergeQueryBuilder<DB, TT, ST, Partial<O2>> {\n    if (condition) {\n      return func(this) as any\n    }\n\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n    }) as any\n  }\n\n  toOperationNode(): MergeQueryNode {\n    return this.#props.executor.transformQuery(\n      this.#props.queryNode,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery<O> {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  /**\n   * Executes the query and returns an array of rows.\n   *\n   * Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.\n   */\n  async execute(): Promise<SimplifyResult<O>[]> {\n    const compiledQuery = this.compile()\n\n    const result = await this.#props.executor.executeQuery<O>(compiledQuery)\n\n    const { adapter } = this.#props.executor\n    const query = compiledQuery.query as MergeQueryNode\n\n    if (\n      (query.returning && adapter.supportsReturning) ||\n      (query.output && adapter.supportsOutput)\n    ) {\n      return result.rows as any\n    }\n\n    return [new MergeResult(result.numAffectedRows) as any]\n  }\n\n  /**\n   * Executes the query and returns the first result or undefined if\n   * the query returned no result.\n   */\n  async executeTakeFirst(): Promise<SimplifySingleResult<O>> {\n    const [result] = await this.execute()\n    return result as SimplifySingleResult<O>\n  }\n\n  /**\n   * Executes the query and returns the first result or throws if\n   * the query returned no result.\n   *\n   * By default an instance of {@link NoResultError} is thrown, but you can\n   * provide a custom error class, or callback as the only argument to throw a different\n   * error.\n   */\n  async executeTakeFirstOrThrow(\n    errorConstructor:\n      | NoResultErrorConstructor\n      | ((node: QueryNode) => Error) = NoResultError,\n  ): Promise<SimplifyResult<O>> {\n    const result = await this.executeTakeFirst()\n\n    if (result === undefined) {\n      const error = isNoResultErrorConstructor(errorConstructor)\n        ? new errorConstructor(this.toOperationNode())\n        : errorConstructor(this.toOperationNode())\n\n      throw error\n    }\n\n    return result as SimplifyResult<O>\n  }\n}\n\nexport class MatchedThenableMergeQueryBuilder<\n  DB,\n  TT extends keyof DB,\n  ST extends keyof DB,\n  UT extends TT | ST,\n  O,\n> {\n  readonly #props: MergeQueryBuilderProps\n\n  constructor(props: MergeQueryBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Performs the `delete` action.\n   *\n   * To perform the `do nothing` action, see {@link thenDoNothing}.\n   *\n   * To perform the `update` action, see {@link thenUpdate} or {@link thenUpdateSet}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenMatched()\n   *   .thenDelete()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when matched then\n   *   delete\n   * ```\n   */\n  thenDelete(): WheneableMergeQueryBuilder<DB, TT, ST, O> {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: MergeQueryNode.cloneWithThen(\n        this.#props.queryNode,\n        parseMergeThen('delete'),\n      ),\n    })\n  }\n\n  /**\n   * Performs the `do nothing` action.\n   *\n   * This is supported in PostgreSQL.\n   *\n   * To perform the `delete` action, see {@link thenDelete}.\n   *\n   * To perform the `update` action, see {@link thenUpdate} or {@link thenUpdateSet}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenMatched()\n   *   .thenDoNothing()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when matched then\n   *   do nothing\n   * ```\n   */\n  thenDoNothing(): WheneableMergeQueryBuilder<DB, TT, ST, O> {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: MergeQueryNode.cloneWithThen(\n        this.#props.queryNode,\n        parseMergeThen('do nothing'),\n      ),\n    })\n  }\n\n  /**\n   * Perform an `update` operation with a full-fledged {@link UpdateQueryBuilder}.\n   * This is handy when multiple `set` invocations are needed.\n   *\n   * For a shorthand version of this method, see {@link thenUpdateSet}.\n   *\n   * To perform the `delete` action, see {@link thenDelete}.\n   *\n   * To perform the `do nothing` action, see {@link thenDoNothing}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenMatched()\n   *   .thenUpdate((ub) => ub\n   *     .set(sql`metadata['has_pets']`, 'Y')\n   *     .set({\n   *       updated_at: new Date().toISOString(),\n   *     })\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when matched then\n   *   update set metadata['has_pets'] = $1, \"updated_at\" = $2\n   * ```\n   */\n  thenUpdate<QB extends UpdateQueryBuilder<DB, TT, UT, never>>(\n    set: (ub: QB) => QB,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, O> {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: MergeQueryNode.cloneWithThen(\n        this.#props.queryNode,\n        parseMergeThen(\n          set(\n            new UpdateQueryBuilder({\n              queryId: this.#props.queryId,\n              executor: NOOP_QUERY_EXECUTOR,\n              queryNode: UpdateQueryNode.createWithoutTable(),\n            }) as QB,\n          ),\n        ),\n      ),\n    })\n  }\n\n  /**\n   * Performs an `update set` action, similar to {@link UpdateQueryBuilder.set}.\n   *\n   * For a full-fledged update query builder, see {@link thenUpdate}.\n   *\n   * To perform the `delete` action, see {@link thenDelete}.\n   *\n   * To perform the `do nothing` action, see {@link thenDoNothing}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenMatched()\n   *   .thenUpdateSet({\n   *     middle_name: 'dog owner',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generate SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when matched then\n   *   update set \"middle_name\" = $1\n   * ```\n   */\n  thenUpdateSet<UO extends UpdateObject<DB, UT, TT>>(\n    update: UO,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, O>\n\n  thenUpdateSet<U extends UpdateObjectFactory<DB, UT, TT>>(\n    update: U,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, O>\n\n  thenUpdateSet<\n    RE extends ReferenceExpression<DB, TT>,\n    VE extends ValueExpression<\n      DB,\n      UT,\n      ExtractUpdateTypeFromReferenceExpression<DB, TT, RE>\n    >,\n  >(key: RE, value: VE): WheneableMergeQueryBuilder<DB, TT, ST, O>\n\n  thenUpdateSet(...args: any[]): any {\n    // @ts-ignore not sure how to type this so it won't complain about set(...args).\n    return this.thenUpdate((ub) => ub.set(...args))\n  }\n}\n\nexport class NotMatchedThenableMergeQueryBuilder<\n  DB,\n  TT extends keyof DB,\n  ST extends keyof DB,\n  O,\n> {\n  readonly #props: MergeQueryBuilderProps\n\n  constructor(props: MergeQueryBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Performs the `do nothing` action.\n   *\n   * This is supported in PostgreSQL.\n   *\n   * To perform the `insert` action, see {@link thenInsertValues}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenNotMatched()\n   *   .thenDoNothing()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when not matched then\n   *   do nothing\n   * ```\n   */\n  thenDoNothing(): WheneableMergeQueryBuilder<DB, TT, ST, O> {\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: MergeQueryNode.cloneWithThen(\n        this.#props.queryNode,\n        parseMergeThen('do nothing'),\n      ),\n    })\n  }\n\n  /**\n   * Performs the `insert (...) values` action.\n   *\n   * This method is similar to {@link InsertQueryBuilder.values}, so see the documentation\n   * for that method for more examples.\n   *\n   * To perform the `do nothing` action, see {@link thenDoNothing}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.mergeInto('person')\n   *   .using('pet', 'person.id', 'pet.owner_id')\n   *   .whenNotMatched()\n   *   .thenInsertValues({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *   })\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"person\".\"id\" = \"pet\".\"owner_id\"\n   * when not matched then\n   *   insert (\"first_name\", \"last_name\") values ($1, $2)\n   * ```\n   */\n  thenInsertValues<I extends InsertObjectOrList<DB, TT>>(\n    insert: I,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, O>\n\n  thenInsertValues<IO extends InsertObjectOrListFactory<DB, TT, ST>>(\n    insert: IO,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, O>\n\n  thenInsertValues<IE extends InsertExpression<DB, TT, ST>>(\n    insert: IE,\n  ): WheneableMergeQueryBuilder<DB, TT, ST, O> {\n    const [columns, values] = parseInsertExpression(insert)\n\n    return new WheneableMergeQueryBuilder({\n      ...this.#props,\n      queryNode: MergeQueryNode.cloneWithThen(\n        this.#props.queryNode,\n        parseMergeThen(\n          InsertQueryNode.cloneWith(InsertQueryNode.createWithoutInto(), {\n            columns,\n            values,\n          }),\n        ),\n      ),\n    })\n  }\n}\n\nexport type ExtractWheneableMergeQueryBuilder<\n  DB,\n  TT extends keyof DB,\n  TE extends TableExpression<DB, TT>,\n  O,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? UsingBuilder<DB, TT, A, DB[T], O>\n    : never\n  : TE extends keyof DB\n    ? WheneableMergeQueryBuilder<DB, TT, TE, O>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? UsingBuilder<DB, TT, QA, QO, O>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? UsingBuilder<DB, TT, QA, QO, O>\n        : never\n\ntype UsingBuilder<\n  DB,\n  TT extends keyof DB,\n  A extends string,\n  R,\n  O,\n> = A extends keyof DB\n  ? WheneableMergeQueryBuilder<DB, TT, A, O>\n  : WheneableMergeQueryBuilder<DB & ShallowRecord<A, R>, TT, A, O>\n"
  },
  {
    "path": "src/query-builder/merge-result.ts",
    "content": "export class MergeResult {\n  readonly numChangedRows: bigint | undefined\n\n  constructor(numChangedRows: bigint | undefined) {\n    this.numChangedRows = numChangedRows\n  }\n}\n"
  },
  {
    "path": "src/query-builder/no-result-error.ts",
    "content": "import type { QueryNode } from '../operation-node/query-node.js'\n\nexport type NoResultErrorConstructor = new (node: QueryNode) => Error\n\nexport class NoResultError extends Error {\n  /**\n   * The operation node tree of the query that was executed.\n   */\n  readonly node: QueryNode\n\n  constructor(node: QueryNode) {\n    super('no result')\n    this.node = node\n  }\n}\n\nexport function isNoResultErrorConstructor(\n  fn: NoResultErrorConstructor | ((node: QueryNode) => Error),\n): fn is NoResultErrorConstructor {\n  return Object.prototype.hasOwnProperty.call(fn, 'prototype')\n}\n"
  },
  {
    "path": "src/query-builder/on-conflict-builder.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport { ColumnNode } from '../operation-node/column-node.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport { OnConflictNode } from '../operation-node/on-conflict-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport {\n  type ComparisonOperatorExpression,\n  type OperandValueExpressionOrList,\n  parseValueBinaryOperationOrExpression,\n  parseReferentialBinaryOperation,\n} from '../parser/binary-operation-parser.js'\nimport type { ExpressionOrFactory } from '../parser/expression-parser.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport {\n  type UpdateObjectExpression,\n  parseUpdateObjectExpression,\n} from '../parser/update-set-parser.js'\nimport type { Updateable } from '../util/column-type.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { AnyColumn, SqlBool } from '../util/type-utils.js'\nimport type { WhereInterface } from './where-interface.js'\n\nexport class OnConflictBuilder<\n  DB,\n  TB extends keyof DB,\n> implements WhereInterface<DB, TB> {\n  readonly #props: OnConflictBuilderProps\n\n  constructor(props: OnConflictBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Specify a single column as the conflict target.\n   *\n   * Also see the {@link columns}, {@link constraint} and {@link expression}\n   * methods for alternative ways to specify the conflict target.\n   */\n  column(column: AnyColumn<DB, TB>): OnConflictBuilder<DB, TB> {\n    const columnNode = ColumnNode.create(column)\n\n    return new OnConflictBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWith(this.#props.onConflictNode, {\n        columns: this.#props.onConflictNode.columns\n          ? freeze([...this.#props.onConflictNode.columns, columnNode])\n          : freeze([columnNode]),\n      }),\n    })\n  }\n\n  /**\n   * Specify a list of columns as the conflict target.\n   *\n   * Also see the {@link column}, {@link constraint} and {@link expression}\n   * methods for alternative ways to specify the conflict target.\n   */\n  columns(\n    columns: ReadonlyArray<AnyColumn<DB, TB>>,\n  ): OnConflictBuilder<DB, TB> {\n    const columnNodes = columns.map(ColumnNode.create)\n\n    return new OnConflictBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWith(this.#props.onConflictNode, {\n        columns: this.#props.onConflictNode.columns\n          ? freeze([...this.#props.onConflictNode.columns, ...columnNodes])\n          : freeze(columnNodes),\n      }),\n    })\n  }\n\n  /**\n   * Specify a specific constraint by name as the conflict target.\n   *\n   * Also see the {@link column}, {@link columns} and {@link expression}\n   * methods for alternative ways to specify the conflict target.\n   */\n  constraint(constraintName: string): OnConflictBuilder<DB, TB> {\n    return new OnConflictBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWith(this.#props.onConflictNode, {\n        constraint: IdentifierNode.create(constraintName),\n      }),\n    })\n  }\n\n  /**\n   * Specify an expression as the conflict target.\n   *\n   * This can be used if the unique index is an expression index.\n   *\n   * Also see the {@link column}, {@link columns} and {@link constraint}\n   * methods for alternative ways to specify the conflict target.\n   */\n  expression(expression: Expression<any>): OnConflictBuilder<DB, TB> {\n    return new OnConflictBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWith(this.#props.onConflictNode, {\n        indexExpression: expression.toOperationNode(),\n      }),\n    })\n  }\n\n  where<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): OnConflictBuilder<DB, TB>\n\n  where<E extends ExpressionOrFactory<DB, TB, SqlBool>>(\n    expression: E,\n  ): OnConflictBuilder<DB, TB>\n\n  where(...args: any[]): OnConflictBuilder<DB, TB> {\n    return new OnConflictBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWithIndexWhere(\n        this.#props.onConflictNode,\n        parseValueBinaryOperationOrExpression(args),\n      ),\n    })\n  }\n\n  whereRef<\n    LRE extends ReferenceExpression<DB, TB>,\n    RRE extends ReferenceExpression<DB, TB>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): OnConflictBuilder<DB, TB> {\n    return new OnConflictBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWithIndexWhere(\n        this.#props.onConflictNode,\n        parseReferentialBinaryOperation(lhs, op, rhs),\n      ),\n    })\n  }\n\n  clearWhere(): OnConflictBuilder<DB, TB> {\n    return new OnConflictBuilder<DB, TB>({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWithoutIndexWhere(\n        this.#props.onConflictNode,\n      ),\n    })\n  }\n\n  /**\n   * Adds the \"do nothing\" conflict action.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const id = 1\n   * const first_name = 'John'\n   *\n   * await db\n   *   .insertInto('person')\n   *   .values({ first_name, id })\n   *   .onConflict((oc) => oc\n   *     .column('id')\n   *     .doNothing()\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"id\")\n   * values ($1, $2)\n   * on conflict (\"id\") do nothing\n   * ```\n   */\n  doNothing(): OnConflictDoNothingBuilder<DB, TB> {\n    return new OnConflictDoNothingBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWith(this.#props.onConflictNode, {\n        doNothing: true,\n      }),\n    })\n  }\n\n  /**\n   * Adds the \"do update set\" conflict action.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const id = 1\n   * const first_name = 'John'\n   *\n   * await db\n   *   .insertInto('person')\n   *   .values({ first_name, id })\n   *   .onConflict((oc) => oc\n   *     .column('id')\n   *     .doUpdateSet({ first_name })\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"id\")\n   * values ($1, $2)\n   * on conflict (\"id\")\n   * do update set \"first_name\" = $3\n   * ```\n   *\n   * In the next example we use the `ref` method to reference\n   * columns of the virtual table `excluded` in a type-safe way\n   * to create an upsert operation:\n   *\n   * ```ts\n   * import type { NewPerson } from 'type-editor' // imaginary module\n   *\n   * async function upsertPerson(person: NewPerson): Promise<void> {\n   *   await db.insertInto('person')\n   *     .values(person)\n   *     .onConflict((oc) => oc\n   *       .column('id')\n   *       .doUpdateSet((eb) => ({\n   *         first_name: eb.ref('excluded.first_name'),\n   *         last_name: eb.ref('excluded.last_name')\n   *       })\n   *     )\n   *   )\n   *   .execute()\n   * }\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"last_name\")\n   * values ($1, $2)\n   * on conflict (\"id\")\n   * do update set\n   *  \"first_name\" = excluded.\"first_name\",\n   *  \"last_name\" = excluded.\"last_name\"\n   * ```\n   */\n  doUpdateSet(\n    update: UpdateObjectExpression<\n      OnConflictDatabase<DB, TB>,\n      OnConflictTables<TB>,\n      OnConflictTables<TB>\n    >,\n  ): OnConflictUpdateBuilder<OnConflictDatabase<DB, TB>, OnConflictTables<TB>> {\n    return new OnConflictUpdateBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWith(this.#props.onConflictNode, {\n        updates: parseUpdateObjectExpression(update),\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n}\n\nexport interface OnConflictBuilderProps {\n  readonly onConflictNode: OnConflictNode\n}\n\nexport type OnConflictDatabase<DB, TB extends keyof DB> = {\n  [K in keyof DB | 'excluded']: Updateable<K extends keyof DB ? DB[K] : DB[TB]>\n}\n\nexport type OnConflictTables<TB> = TB | 'excluded'\n\nexport class OnConflictDoNothingBuilder<\n  DB,\n  TB extends keyof DB,\n> implements OperationNodeSource {\n  readonly #props: OnConflictBuilderProps\n\n  constructor(props: OnConflictBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  toOperationNode(): OnConflictNode {\n    return this.#props.onConflictNode\n  }\n}\n\nexport class OnConflictUpdateBuilder<DB, TB extends keyof DB>\n  implements WhereInterface<DB, TB>, OperationNodeSource\n{\n  readonly #props: OnConflictBuilderProps\n\n  constructor(props: OnConflictBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Specify a where condition for the update operation.\n   *\n   * See {@link WhereInterface.where} for more info.\n   */\n  where<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): OnConflictUpdateBuilder<DB, TB>\n\n  where<E extends ExpressionOrFactory<DB, TB, SqlBool>>(\n    expression: E,\n  ): OnConflictUpdateBuilder<DB, TB>\n\n  where(...args: any[]): OnConflictUpdateBuilder<DB, TB> {\n    return new OnConflictUpdateBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWithUpdateWhere(\n        this.#props.onConflictNode,\n        parseValueBinaryOperationOrExpression(args),\n      ),\n    })\n  }\n\n  /**\n   * Specify a where condition for the update operation.\n   *\n   * See {@link WhereInterface.whereRef} for more info.\n   */\n  whereRef<\n    LRE extends ReferenceExpression<DB, TB>,\n    RRE extends ReferenceExpression<DB, TB>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): OnConflictUpdateBuilder<DB, TB> {\n    return new OnConflictUpdateBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWithUpdateWhere(\n        this.#props.onConflictNode,\n        parseReferentialBinaryOperation(lhs, op, rhs),\n      ),\n    })\n  }\n\n  clearWhere(): OnConflictUpdateBuilder<DB, TB> {\n    return new OnConflictUpdateBuilder({\n      ...this.#props,\n      onConflictNode: OnConflictNode.cloneWithoutUpdateWhere(\n        this.#props.onConflictNode,\n      ),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): OnConflictNode {\n    return this.#props.onConflictNode\n  }\n}\n"
  },
  {
    "path": "src/query-builder/order-by-interface.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport type {\n  OrderByExpression,\n  DirectedOrderByStringReference,\n  OrderByModifiers,\n} from '../parser/order-by-parser.js'\n\nexport interface OrderByInterface<DB, TB extends keyof DB, O> {\n  /**\n   * Adds an `order by` clause to the query.\n   *\n   * `orderBy` calls are additive. Meaning, additional `orderBy` calls append to\n   * the existing order by clause.\n   *\n   * `orderBy` is supported in select queries on all dialects. In MySQL, you can\n   * also use `orderBy` in update and delete queries.\n   *\n   * In a single call you can add a single column/expression or multiple columns/expressions.\n   *\n   * Single column/expression calls can have 1-2 arguments. The first argument is\n   * the expression to order by, while the second optional argument is the direction\n   * (`asc` or `desc`), a callback that accepts and returns an {@link OrderByItemBuilder}\n   * or an expression.\n   *\n   * See {@link clearOrderBy} to remove the `order by` clause from a query.\n   *\n   * ### Examples\n   *\n   * Single column/expression per call:\n   *\n   * ```ts\n   * await db\n   *   .selectFrom('person')\n   *   .select('person.first_name as fn')\n   *   .orderBy('id')\n   *   .orderBy('fn', 'desc')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"first_name\" as \"fn\"\n   * from \"person\"\n   * order by \"id\", \"fn\" desc\n   * ```\n   *\n   * Building advanced modifiers:\n   *\n   * ```ts\n   * await db\n   *   .selectFrom('person')\n   *   .select('person.first_name as fn')\n   *   .orderBy('id', (ob) => ob.desc().nullsFirst())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"first_name\" as \"fn\"\n   * from \"person\"\n   * order by \"id\" desc nulls first\n   * ```\n   *\n   * The order by expression can also be a raw sql expression or a subquery\n   * in addition to column references:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .orderBy((eb) => eb.selectFrom('pet')\n   *     .select('pet.name')\n   *     .whereRef('pet.owner_id', '=', 'person.id')\n   *     .limit(1)\n   *   )\n   *   .orderBy(\n   *     sql<string>`concat(first_name, last_name) asc`\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * order by\n   *   ( select \"pet\".\"name\"\n   *     from \"pet\"\n   *     where \"pet\".\"owner_id\" = \"person\".\"id\"\n   *     limit $1\n   *   ) asc,\n   *   concat(first_name, last_name) asc\n   * ```\n   *\n   * `dynamic.ref` can be used to refer to columns not known at\n   * compile time:\n   *\n   * ```ts\n   * async function someQuery(orderBy: string) {\n   *   const { ref } = db.dynamic\n   *\n   *   return await db\n   *     .selectFrom('person')\n   *     .select('person.first_name as fn')\n   *     .orderBy(ref(orderBy))\n   *     .execute()\n   * }\n   *\n   * someQuery('fn')\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"first_name\" as \"fn\"\n   * from \"person\"\n   * order by \"fn\"\n   * ```\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, O>>(\n    expr: OE,\n    modifiers?: OrderByModifiers,\n  ): OrderByInterface<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `orderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.\n   */\n  orderBy<\n    OE extends\n      | OrderByExpression<DB, TB, O>\n      | DirectedOrderByStringReference<DB, TB, O>,\n  >(\n    exprs: ReadonlyArray<OE>,\n  ): OrderByInterface<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated It does ~2.9x more compile-time instantiations compared to a `orderBy(expr, direction)` call.\n   */\n  orderBy<OE extends DirectedOrderByStringReference<DB, TB, O>>(\n    expr: OE,\n  ): OrderByInterface<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated Use `orderBy(expr, (ob) => ...)` instead.\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, O>>(\n    expr: OE,\n    modifiers: Expression<any>,\n  ): OrderByInterface<DB, TB, O>\n\n  /**\n   * Clears the `order by` clause from the query.\n   *\n   * See {@link orderBy} for adding an `order by` clause or item to a query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const query = db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .orderBy('id', 'desc')\n   *\n   * const results = await query\n   *   .clearOrderBy()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\"\n   * ```\n   */\n  clearOrderBy(): OrderByInterface<DB, TB, O>\n}\n"
  },
  {
    "path": "src/query-builder/order-by-item-builder.ts",
    "content": "import { CollateNode } from '../operation-node/collate-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { OrderByItemNode } from '../operation-node/order-by-item-node.js'\nimport { RawNode } from '../operation-node/raw-node.js'\nimport type { Collation } from '../parser/collate-parser.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport class OrderByItemBuilder implements OperationNodeSource {\n  readonly #props: OrderByItemBuilderProps\n\n  constructor(props: OrderByItemBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Adds `desc` to the `order by` item.\n   *\n   * See {@link asc} for the opposite.\n   */\n  desc(): OrderByItemBuilder {\n    return new OrderByItemBuilder({\n      node: OrderByItemNode.cloneWith(this.#props.node, {\n        direction: RawNode.createWithSql('desc'),\n      }),\n    })\n  }\n\n  /**\n   * Adds `asc` to the `order by` item.\n   *\n   * See {@link desc} for the opposite.\n   */\n  asc(): OrderByItemBuilder {\n    return new OrderByItemBuilder({\n      node: OrderByItemNode.cloneWith(this.#props.node, {\n        direction: RawNode.createWithSql('asc'),\n      }),\n    })\n  }\n\n  /**\n   * Adds `nulls last` to the `order by` item.\n   *\n   * This is only supported by some dialects like PostgreSQL and SQLite.\n   *\n   * See {@link nullsFirst} for the opposite.\n   */\n  nullsLast(): OrderByItemBuilder {\n    return new OrderByItemBuilder({\n      node: OrderByItemNode.cloneWith(this.#props.node, { nulls: 'last' }),\n    })\n  }\n\n  /**\n   * Adds `nulls first` to the `order by` item.\n   *\n   * This is only supported by some dialects like PostgreSQL and SQLite.\n   *\n   * See {@link nullsLast} for the opposite.\n   */\n  nullsFirst(): OrderByItemBuilder {\n    return new OrderByItemBuilder({\n      node: OrderByItemNode.cloneWith(this.#props.node, { nulls: 'first' }),\n    })\n  }\n\n  /**\n   * Adds `collate <collationName>` to the `order by` item.\n   */\n  collate(collation: Collation): OrderByItemBuilder {\n    return new OrderByItemBuilder({\n      node: OrderByItemNode.cloneWith(this.#props.node, {\n        collation: CollateNode.create(collation),\n      }),\n    })\n  }\n\n  toOperationNode(): OrderByItemNode {\n    return this.#props.node\n  }\n}\n\nexport interface OrderByItemBuilderProps {\n  readonly node: OrderByItemNode\n}\n"
  },
  {
    "path": "src/query-builder/output-interface.ts",
    "content": "import type { ExpressionBuilder } from '../expression/expression-builder.js'\nimport type { AliasedExpressionOrFactory } from '../parser/expression-parser.js'\nimport type {\n  ReturningAllRow,\n  ReturningRow,\n} from '../parser/returning-parser.js'\nimport type {\n  AnyAliasedColumnWithTable,\n  AnyColumnWithTable,\n} from '../util/type-utils.js'\n\nexport interface OutputInterface<\n  DB,\n  TB extends keyof DB,\n  O,\n  OP extends OutputPrefix = OutputPrefix,\n> {\n  /**\n   * Allows you to return data from modified rows.\n   *\n   * On supported databases like MS SQL Server (MSSQL), this method can be chained\n   * to `insert`, `update`, `delete` and `merge` queries to return data.\n   *\n   * Also see the {@link outputAll} method.\n   *\n   * ### Examples\n   *\n   * Return one column:\n   *\n   * ```ts\n   * const { id } = await db\n   *   .insertInto('person')\n   *   .output('inserted.id')\n   *   .values({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston',\n   *     gender: 'female',\n   *   })\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (MSSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"last_name\", \"gender\")\n   * output \"inserted\".\"id\"\n   * values (@1, @2, @3)\n   * ```\n   *\n   * Return multiple columns:\n   *\n   * ```ts\n   * const { old_first_name, old_last_name, new_first_name, new_last_name } = await db\n   *   .updateTable('person')\n   *   .set({ first_name: 'John', last_name: 'Doe' })\n   *   .output([\n   *     'deleted.first_name as old_first_name',\n   *     'deleted.last_name as old_last_name',\n   *     'inserted.first_name as new_first_name',\n   *     'inserted.last_name as new_last_name',\n   *   ])\n   *   .where('created_at', '<', new Date())\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (MSSQL):\n   *\n   * ```sql\n   * update \"person\"\n   * set \"first_name\" = @1, \"last_name\" = @2\n   * output \"deleted\".\"first_name\" as \"old_first_name\",\n   *   \"deleted\".\"last_name\" as \"old_last_name\",\n   *   \"inserted\".\"first_name\" as \"new_first_name\",\n   *   \"inserted\".\"last_name\" as \"new_last_name\"\n   * where \"created_at\" < @3\n   * ```\n   *\n   * Return arbitrary expressions:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const { full_name } = await db\n   *   .deleteFrom('person')\n   *   .output((eb) => sql<string>`concat(${eb.ref('deleted.first_name')}, ' ', ${eb.ref('deleted.last_name')})`.as('full_name'))\n   *   .where('created_at', '<', new Date())\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (MSSQL):\n   *\n   * ```sql\n   * delete from \"person\"\n   * output concat(\"deleted\".\"first_name\", ' ', \"deleted\".\"last_name\") as \"full_name\"\n   * where \"created_at\" < @1\n   * ```\n   *\n   * Return the action performed on the row:\n   *\n   * ```ts\n   * await db\n   *   .mergeInto('person')\n   *   .using('pet', 'pet.owner_id', 'person.id')\n   *   .whenMatched()\n   *   .thenDelete()\n   *   .whenNotMatched()\n   *   .thenInsertValues({\n   *     first_name: 'John',\n   *     last_name: 'Doe',\n   *     gender: 'male'\n   *   })\n   *   .output([\n   *     'inserted.id as inserted_id',\n   *     'deleted.id as deleted_id',\n   *   ])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MSSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * when matched then delete\n   * when not matched then\n   * insert (\"first_name\", \"last_name\", \"gender\")\n   * values (@1, @2, @3)\n   * output \"inserted\".\"id\" as \"inserted_id\", \"deleted\".\"id\" as \"deleted_id\"\n   * ```\n   *\n   */\n  output<OE extends OutputExpression<DB, TB, OP>>(\n    selections: ReadonlyArray<OE>,\n  ): OutputInterface<\n    DB,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>,\n    OP\n  >\n\n  output<CB extends OutputCallback<DB, TB, OP>>(\n    callback: CB,\n  ): OutputInterface<\n    DB,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputCallback<CB>>,\n    OP\n  >\n\n  output<OE extends OutputExpression<DB, TB, OP>>(\n    selection: OE,\n  ): OutputInterface<\n    DB,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>,\n    OP\n  >\n\n  /**\n   * Adds an `output {prefix}.*` to an `insert`/`update`/`delete`/`merge` query on databases\n   * that support `output` such as MS SQL Server (MSSQL).\n   *\n   * Also see the {@link output} method.\n   */\n  outputAll(table: OP): OutputInterface<DB, TB, ReturningAllRow<DB, TB, O>, OP>\n}\n\nexport type OutputPrefix = 'deleted' | 'inserted'\n\nexport type OutputDatabase<\n  DB,\n  TB extends keyof DB,\n  OP extends OutputPrefix = OutputPrefix,\n> = {\n  [K in OP]: DB[TB]\n}\n\nexport type OutputExpression<\n  DB,\n  TB extends keyof DB,\n  OP extends OutputPrefix = OutputPrefix,\n  ODB = OutputDatabase<DB, TB, OP>,\n  OTB extends keyof ODB = keyof ODB,\n> =\n  | AnyAliasedColumnWithTable<ODB, OTB>\n  | AnyColumnWithTable<ODB, OTB>\n  | AliasedExpressionOrFactory<ODB, OTB>\n\nexport type OutputCallback<\n  DB,\n  TB extends keyof DB,\n  OP extends OutputPrefix = OutputPrefix,\n> = (\n  eb: ExpressionBuilder<OutputDatabase<DB, TB, OP>, OP>,\n) => ReadonlyArray<OutputExpression<DB, TB, OP>>\n\nexport type SelectExpressionFromOutputExpression<OE> =\n  OE extends `${OutputPrefix}.${infer C}` ? C : OE\n\nexport type SelectExpressionFromOutputCallback<CB> = CB extends (\n  eb: ExpressionBuilder<any, any>,\n) => ReadonlyArray<infer OE>\n  ? SelectExpressionFromOutputExpression<OE>\n  : never\n"
  },
  {
    "path": "src/query-builder/over-builder.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { OverNode } from '../operation-node/over-node.js'\nimport { QueryNode } from '../operation-node/query-node.js'\nimport {\n  type DirectedOrderByStringReference,\n  type OrderByExpression,\n  type OrderByModifiers,\n  parseOrderBy,\n} from '../parser/order-by-parser.js'\nimport {\n  parsePartitionBy,\n  type PartitionByExpression,\n  type PartitionByExpressionOrList,\n} from '../parser/partition-by-parser.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { OrderByInterface } from './order-by-interface.js'\n\nexport class OverBuilder<DB, TB extends keyof DB>\n  implements OrderByInterface<DB, TB, {}>, OperationNodeSource\n{\n  readonly #props: OverBuilderProps\n\n  constructor(props: OverBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Adds an `order by` clause or item inside the `over` function.\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select(\n   *     (eb) => eb.fn.avg<number>('age').over(\n   *       ob => ob.orderBy('first_name', 'asc').orderBy('last_name', 'asc')\n   *     ).as('average_age')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select avg(\"age\") over(order by \"first_name\" asc, \"last_name\" asc) as \"average_age\"\n   * from \"person\"\n   * ```\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers?: OrderByModifiers,\n  ): OverBuilder<DB, TB>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `orderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.\n   */\n  orderBy<\n    OE extends\n      | OrderByExpression<DB, TB, {}>\n      | DirectedOrderByStringReference<DB, TB, {}>,\n  >(exprs: ReadonlyArray<OE>): OverBuilder<DB, TB>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated It does ~2.9x more compile-time instantiations compared to a `orderBy(expr, direction)` call.\n   */\n  orderBy<OE extends DirectedOrderByStringReference<DB, TB, {}>>(\n    expr: OE,\n  ): OverBuilder<DB, TB>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated Use `orderBy(expr, (ob) => ...)` instead.\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers: Expression<any>,\n  ): OverBuilder<DB, TB>\n\n  orderBy(...args: any[]): any {\n    return new OverBuilder({\n      overNode: OverNode.cloneWithOrderByItems(\n        this.#props.overNode,\n        parseOrderBy(args),\n      ),\n    })\n  }\n\n  clearOrderBy(): OverBuilder<DB, TB> {\n    return new OverBuilder({\n      overNode: QueryNode.cloneWithoutOrderBy(this.#props.overNode),\n    })\n  }\n\n  /**\n   * Adds partition by clause item/s inside the over function.\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select(\n   *     (eb) => eb.fn.avg<number>('age').over(\n   *       ob => ob.partitionBy(['last_name', 'first_name'])\n   *     ).as('average_age')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select avg(\"age\") over(partition by \"last_name\", \"first_name\") as \"average_age\"\n   * from \"person\"\n   * ```\n   */\n  partitionBy(\n    partitionBy: ReadonlyArray<PartitionByExpression<DB, TB>>,\n  ): OverBuilder<DB, TB>\n\n  partitionBy<PE extends PartitionByExpression<DB, TB>>(\n    partitionBy: PE,\n  ): OverBuilder<DB, TB>\n\n  partitionBy(partitionBy: PartitionByExpressionOrList<DB, TB>): any {\n    return new OverBuilder({\n      overNode: OverNode.cloneWithPartitionByItems(\n        this.#props.overNode,\n        parsePartitionBy(partitionBy),\n      ),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): OverNode {\n    return this.#props.overNode\n  }\n}\n\nexport interface OverBuilderProps {\n  readonly overNode: OverNode\n}\n"
  },
  {
    "path": "src/query-builder/returning-interface.ts",
    "content": "import type {\n  ReturningAllRow,\n  ReturningCallbackRow,\n  ReturningRow,\n} from '../parser/returning-parser.js'\nimport type {\n  SelectCallback,\n  SelectExpression,\n} from '../parser/select-parser.js'\nimport type { Selectable } from '../util/column-type.js'\n\nexport interface ReturningInterface<DB, TB extends keyof DB, O> {\n  /**\n   * Allows you to return data from modified rows.\n   *\n   * On supported databases like PostgreSQL, this method can be chained to\n   * `insert`, `update`, `delete` and `merge` queries to return data.\n   *\n   * Note that on SQLite you need to give aliases for the expressions to avoid\n   * [this bug](https://sqlite.org/forum/forumpost/033daf0b32) in SQLite.\n   * For example `.returning('id as id')`.\n   *\n   * Also see the {@link returningAll} method.\n   *\n   * ### Examples\n   *\n   * Return one column:\n   *\n   * ```ts\n   * const { id } = await db\n   *   .insertInto('person')\n   *   .values({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   })\n   *   .returning('id')\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * Return multiple columns:\n   *\n   * ```ts\n   * const { id, last_name } = await db\n   *   .insertInto('person')\n   *   .values({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   })\n   *   .returning(['id', 'last_name'])\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * Return arbitrary expressions:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const { id, full_name, first_pet_id } = await db\n   *   .insertInto('person')\n   *   .values({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   })\n   *   .returning((eb) => [\n   *     'id as id',\n   *     sql<string>`concat(first_name, ' ', last_name)`.as('full_name'),\n   *     eb.selectFrom('pet').select('pet.id').limit(1).as('first_pet_id')\n   *   ])\n   *   .executeTakeFirstOrThrow()\n   * ```\n   */\n  returning<SE extends SelectExpression<DB, TB>>(\n    selections: ReadonlyArray<SE>,\n  ): ReturningInterface<DB, TB, ReturningRow<DB, TB, O, SE>>\n\n  returning<CB extends SelectCallback<DB, TB>>(\n    callback: CB,\n  ): ReturningInterface<DB, TB, ReturningCallbackRow<DB, TB, O, CB>>\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selection: SE,\n  ): ReturningInterface<DB, TB, ReturningRow<DB, TB, O, SE>>\n\n  /**\n   * Adds a `returning *` to an insert/update/delete/merge query on databases\n   * that support `returning` such as PostgreSQL.\n   *\n   * Also see the {@link returning} method.\n   */\n  returningAll(): ReturningInterface<DB, TB, Selectable<DB[TB]>>\n}\n\nexport interface MultiTableReturningInterface<\n  DB,\n  TB extends keyof DB,\n  O,\n> extends ReturningInterface<DB, TB, O> {\n  /**\n   * Adds a `returning *` or `returning table.*` to an insert/update/delete/merge\n   * query on databases that support `returning` such as PostgreSQL.\n   *\n   * Also see the {@link returning} method.\n   */\n  returningAll<T extends TB>(\n    tables: ReadonlyArray<T>,\n  ): MultiTableReturningInterface<DB, TB, ReturningAllRow<DB, T, O>>\n\n  returningAll<T extends TB>(\n    table: T,\n  ): MultiTableReturningInterface<DB, TB, ReturningAllRow<DB, T, O>>\n\n  returningAll(): ReturningInterface<DB, TB, Selectable<DB[TB]>>\n}\n"
  },
  {
    "path": "src/query-builder/select-query-builder-expression.ts",
    "content": "import type { AliasableExpression } from '../expression/expression.js'\nimport type { SelectQueryNode } from '../operation-node/select-query-node.js'\n\nexport interface SelectQueryBuilderExpression<\n  O,\n> extends AliasableExpression<O> {\n  get isSelectQueryBuilder(): true\n  toOperationNode(): SelectQueryNode\n}\n"
  },
  {
    "path": "src/query-builder/select-query-builder.ts",
    "content": "import { AliasNode } from '../operation-node/alias-node.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport { SelectModifierNode } from '../operation-node/select-modifier-node.js'\nimport {\n  type JoinCallbackExpression,\n  type JoinReferenceExpression,\n  parseJoin,\n} from '../parser/join-parser.js'\nimport { type TableExpression, parseTable } from '../parser/table-parser.js'\nimport {\n  parseSelectArg,\n  parseSelectAll,\n  type SelectExpression,\n  type Selection,\n  type SelectArg,\n  type AllSelection,\n  type SelectCallback,\n  type CallbackSelection,\n} from '../parser/select-parser.js'\nimport {\n  parseReferenceExpressionOrList,\n  type ReferenceExpression,\n  type ReferenceExpressionOrList,\n} from '../parser/reference-parser.js'\nimport { SelectQueryNode } from '../operation-node/select-query-node.js'\nimport { QueryNode } from '../operation-node/query-node.js'\nimport type {\n  DrainOuterGeneric,\n  NarrowPartial,\n  Nullable,\n  ShallowRecord,\n  Simplify,\n  SimplifySingleResult,\n  SqlBool,\n} from '../util/type-utils.js'\nimport {\n  type DirectedOrderByStringReference,\n  type OrderByExpression,\n  type OrderByModifiers,\n  parseOrderBy,\n} from '../parser/order-by-parser.js'\nimport { LimitNode } from '../operation-node/limit-node.js'\nimport { OffsetNode } from '../operation-node/offset-node.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { asArray, freeze } from '../util/object-utils.js'\nimport { type GroupByArg, parseGroupBy } from '../parser/group-by-parser.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport type { WhereInterface } from './where-interface.js'\nimport {\n  isNoResultErrorConstructor,\n  NoResultError,\n  type NoResultErrorConstructor,\n} from './no-result-error.js'\nimport type { HavingInterface } from './having-interface.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport type { Explainable, ExplainFormat } from '../util/explainable.js'\nimport {\n  type SetOperandExpression,\n  parseSetOperations,\n} from '../parser/set-operation-parser.js'\nimport type { AliasedExpression, Expression } from '../expression/expression.js'\nimport {\n  type ComparisonOperatorExpression,\n  type OperandValueExpressionOrList,\n  parseValueBinaryOperationOrExpression,\n  parseReferentialBinaryOperation,\n} from '../parser/binary-operation-parser.js'\nimport type { KyselyTypeError } from '../util/type-error.js'\nimport type { Selectable } from '../util/column-type.js'\nimport type { Streamable } from '../util/streamable.js'\nimport type { ExpressionOrFactory } from '../parser/expression-parser.js'\nimport { ExpressionWrapper } from '../expression/expression-wrapper.js'\nimport type { SelectQueryBuilderExpression } from './select-query-builder-expression.js'\nimport {\n  type ValueExpression,\n  parseValueExpression,\n} from '../parser/value-parser.js'\nimport type { FetchModifier } from '../operation-node/fetch-node.js'\nimport { parseFetch } from '../parser/fetch-parser.js'\nimport type { TopModifier } from '../operation-node/top-node.js'\nimport { parseTop } from '../parser/top-parser.js'\nimport type { JoinType } from '../operation-node/join-node.js'\nimport type { OrderByInterface } from './order-by-interface.js'\n\nexport interface SelectQueryBuilder<DB, TB extends keyof DB, O>\n  extends\n    WhereInterface<DB, TB>,\n    HavingInterface<DB, TB>,\n    OrderByInterface<DB, TB, O>,\n    SelectQueryBuilderExpression<O>,\n    Compilable<O>,\n    Explainable,\n    Streamable<O> {\n  where<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  where<E extends ExpressionOrFactory<DB, TB, SqlBool>>(\n    expression: E,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  whereRef<\n    LRE extends ReferenceExpression<DB, TB>,\n    RRE extends ReferenceExpression<DB, TB>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  having<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  having<E extends ExpressionOrFactory<DB, TB, SqlBool>>(\n    expression: E,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  havingRef<\n    LRE extends ReferenceExpression<DB, TB>,\n    RRE extends ReferenceExpression<DB, TB>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds a select statement to the query.\n   *\n   * When a column (or any expression) is selected, Kysely adds its type to the return\n   * type of the query. Kysely is smart enough to parse the selection names and types\n   * from aliased columns, subqueries, raw expressions etc.\n   *\n   * Kysely only allows you to select columns and expressions that exist and would\n   * produce valid SQL. However, Kysely is not perfect and there may be cases where\n   * the type inference doesn't work and you need to override it. You can always\n   * use the {@link Kysely.dynamic | dynamic} module and the {@link sql} tag\n   * to override the types.\n   *\n   * Select calls are additive. Calling `select('id').select('first_name')` is the\n   * same as calling `select(['id', 'first_name'])`.\n   *\n   * To select all columns of the query or specific tables see the\n   * {@link selectAll} method.\n   *\n   * See the {@link $if} method if you are looking for a way to add selections\n   * based on a runtime condition.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"select\", \"A single column\", 10) -->\n   *\n   * Select a single column:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .select('id')\n   *   .where('first_name', '=', 'Arnold')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\" from \"person\" where \"first_name\" = $1\n   * ```\n   *\n   * <!-- siteExample(\"select\", \"Column with a table\", 20) -->\n   *\n   * Select a single column and specify a table:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom(['person', 'pet'])\n   *   .select('person.id')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"id\" from \"person\", \"pet\"\n   * ```\n   *\n   * <!-- siteExample(\"select\", \"Multiple columns\", 30) -->\n   *\n   * Select multiple columns:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .select(['person.id', 'first_name'])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"id\", \"first_name\" from \"person\"\n   * ```\n   *\n   * <!-- siteExample(\"select\", \"Aliases\", 40) -->\n   *\n   * You can give an alias for selections and tables by appending `as the_alias` to the name:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person as p')\n   *   .select([\n   *     'first_name as fn',\n   *     'p.last_name as ln'\n   *   ])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   \"first_name\" as \"fn\",\n   *   \"p\".\"last_name\" as \"ln\"\n   * from \"person\" as \"p\"\n   * ```\n   *\n   * <!-- siteExample(\"select\", \"Complex selections\", 50) -->\n   *\n   * You can select arbitrary expression including subqueries and raw sql snippets.\n   * When you do that, you need to give a name for the selections using the `as` method:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const persons = await db.selectFrom('person')\n   *   .select(({ eb, selectFrom, or, val, lit }) => [\n   *     // Select a correlated subquery\n   *     selectFrom('pet')\n   *       .whereRef('person.id', '=', 'pet.owner_id')\n   *       .select('pet.name')\n   *       .orderBy('pet.name')\n   *       .limit(1)\n   *       .as('first_pet_name'),\n   *\n   *     // Build and select an expression using\n   *     // the expression builder\n   *     or([\n   *       eb('first_name', '=', 'Jennifer'),\n   *       eb('first_name', '=', 'Arnold')\n   *     ]).as('is_jennifer_or_arnold'),\n   *\n   *     // Select a raw sql expression\n   *     sql<string>`concat(first_name, ' ', last_name)`.as('full_name'),\n   *\n   *     // Select a static string value\n   *     val('Some value').as('string_value'),\n   *\n   *     // Select a literal value\n   *     lit(42).as('literal_value'),\n   *   ])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   (\n   *     select \"pet\".\"name\"\n   *     from \"pet\"\n   *     where \"person\".\"id\" = \"pet\".\"owner_id\"\n   *     order by \"pet\".\"name\"\n   *     limit $1\n   *   ) as \"pet_name\",\n   *   (\"first_name\" = $2 or \"first_name\" = $3) as \"jennifer_or_arnold\",\n   *   concat(first_name, ' ', last_name) as \"full_name\",\n   *   $4 as \"string_value\",\n   *   42 as \"literal_value\"\n   * from \"person\"\n   * ```\n   *\n   * In case you use the {@link sql} tag you need to specify the type of the expression\n   * (in this example `string`).\n   *\n   *  <!-- siteExample(\"select\", \"Not null\", 51) -->\n   *\n   * Sometimes you can be sure something's not null, but Kysely isn't able to infer\n   * it. For example calling `where('last_name', 'is not', null)` doesn't make\n   * `last_name` not null in the result type, but unless you have other where statements\n   * you can be sure it's never null.\n   *\n   * Kysely has a couple of helpers for dealing with these cases: `$notNull()` and `$narrowType`.\n   * Both are used in the following example:\n   *\n   * ```ts\n   * import { NotNull } from 'kysely'\n   * import { jsonObjectFrom } from 'kysely/helpers/postgres'\n   *\n   * const persons = db\n   *   .selectFrom('person')\n   *   .select((eb) => [\n   *     'last_name',\n   *      // Let's assume we know the person has at least one\n   *      // pet. We can use the `.$notNull()` method to make\n   *      // the expression not null. You could just as well\n   *      // add `pet` to the `$narrowType` call below.\n   *      jsonObjectFrom(\n   *        eb.selectFrom('pet')\n   *          .selectAll()\n   *          .limit(1)\n   *          .whereRef('person.id', '=', 'pet.owner_id')\n   *      ).$notNull().as('pet')\n   *   ])\n   *   .where('last_name', 'is not', null)\n   *   // $narrowType can be used to narrow the output type.\n   *   // The special `NotNull` type can be used to make a\n   *   // selection not null. You could add `pet: NotNull`\n   *   // here and omit the `$notNull()` call on it.\n   *   // Use whichever way you prefer.\n   *   .$narrowType<{ last_name: NotNull }>()\n   *   .execute()\n   * ```\n   *\n   * All the examples above assume you know the column names at compile time.\n   * While it's better to build your code like that (that way you also know\n   * the types) sometimes it's not possible or you just prefer to write more\n   * dynamic code.\n   * <br><br>\n   * In this example, we use the `dynamic` module's methods to add selections\n   * dynamically:\n   *\n   * ```ts\n   * const { ref } = db.dynamic\n   *\n   * // Some column name provided by the user. Value not known at compile time.\n   * const columnFromUserInput: string = 'first_name';\n   *\n   * // A type that lists all possible values `columnFromUserInput` can have.\n   * // You can use `keyof Person` if any column of an interface is allowed.\n   * type PossibleColumns = 'last_name' | 'first_name' | 'birthdate'\n   *\n   * const people = await db\n   *   .selectFrom('person')\n   *   .select([\n   *     ref<PossibleColumns>(columnFromUserInput),\n   *     'id'\n   *   ])\n   *   .execute()\n   *\n   * // The resulting type contains all `PossibleColumns` as optional fields\n   * // because we cannot know which field was actually selected before\n   * // running the code.\n   * const lastName: string | null | undefined = people[0].last_name\n   * const firstName: string | undefined = people[0].first_name\n   * const birthDate: Date | null | undefined = people[0].birthdate\n   *\n   * // The result type also contains the compile time selection `id`.\n   * people[0].id\n   * ```\n   */\n  select<SE extends SelectExpression<DB, TB>>(\n    selections: ReadonlyArray<SE>,\n  ): SelectQueryBuilder<DB, TB, O & Selection<DB, TB, SE>>\n\n  select<CB extends SelectCallback<DB, TB>>(\n    callback: CB,\n  ): SelectQueryBuilder<DB, TB, O & CallbackSelection<DB, TB, CB>>\n\n  select<SE extends SelectExpression<DB, TB>>(\n    selection: SE,\n  ): SelectQueryBuilder<DB, TB, O & Selection<DB, TB, SE>>\n\n  /**\n   * Adds `distinct on` expressions to the select clause.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"select\", \"Distinct on\", 80) -->\n   *\n   * ```ts\n   * const persons = await db.selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .where('pet.name', '=', 'Doggo')\n   *   .distinctOn('person.id')\n   *   .selectAll('person')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select distinct on (\"person\".\"id\") \"person\".*\n   * from \"person\"\n   * inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * where \"pet\".\"name\" = $1\n   * ```\n   */\n  distinctOn<RE extends ReferenceExpression<DB, TB>>(\n    selections: ReadonlyArray<RE>,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  distinctOn<RE extends ReferenceExpression<DB, TB>>(\n    selection: RE,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * This can be used to add any additional SQL to the front of the query __after__ the `select` keyword.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.selectFrom('person')\n   *   .modifyFront(sql`sql_no_cache`)\n   *   .select('first_name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * select sql_no_cache `first_name`\n   * from `person`\n   * ```\n   */\n  modifyFront(modifier: Expression<any>): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * This can be used to add any additional SQL to the end of the query.\n   *\n   * Also see {@link forUpdate}, {@link forShare}, {@link forKeyShare}, {@link forNoKeyUpdate}\n   * {@link skipLocked} and  {@link noWait}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.selectFrom('person')\n   *   .select('first_name')\n   *   .modifyEnd(sql`for update`)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\"\n   * from \"person\"\n   * for update\n   * ```\n   */\n  modifyEnd(modifier: Expression<any>): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Makes the selection distinct.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"select\", \"Distinct\", 70) -->\n   *\n   * ```ts\n   * const persons = await db.selectFrom('person')\n   *   .select('first_name')\n   *   .distinct()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select distinct \"first_name\" from \"person\"\n   * ```\n   */\n  distinct(): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds the `for update` modifier to a select query on supported databases.\n   */\n  forUpdate(of?: TableOrList<TB>): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds the `for share` modifier to a select query on supported databases.\n   */\n  forShare(of?: TableOrList<TB>): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds the `for key share` modifier to a select query on supported databases.\n   */\n  forKeyShare(of?: TableOrList<TB>): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds the `for no key update` modifier to a select query on supported databases.\n   */\n  forNoKeyUpdate(of?: TableOrList<TB>): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds the `skip locked` modifier to a select query on supported databases.\n   */\n  skipLocked(): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds the `nowait` modifier to a select query on supported databases.\n   */\n  noWait(): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds a `select *` or `select table.*` clause to the query.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"select\", \"All columns\", 90) -->\n   *\n   * The `selectAll` method generates `SELECT *`:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\"\n   * ```\n   *\n   * <!-- siteExample(\"select\", \"All columns of a table\", 100) -->\n   *\n   * Select all columns of a table:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll('person')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".* from \"person\"\n   * ```\n   *\n   * Select all columns of multiple tables:\n   *\n   * ```ts\n   * const personsPets = await db\n   *   .selectFrom(['person', 'pet'])\n   *   .selectAll(['person', 'pet'])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*, \"pet\".* from \"person\", \"pet\"\n   * ```\n   */\n  selectAll<T extends TB>(\n    table: ReadonlyArray<T>,\n  ): SelectQueryBuilder<DB, TB, O & AllSelection<DB, T>>\n\n  selectAll<T extends TB>(\n    table: T,\n  ): SelectQueryBuilder<DB, TB, O & Selectable<DB[T]>>\n\n  selectAll(): SelectQueryBuilder<DB, TB, O & AllSelection<DB, TB>>\n\n  /**\n   * Joins another table to the query using an `inner join`.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"join\", \"Simple inner join\", 10) -->\n   *\n   * Simple `inner join`s can be done by providing a table name and two columns to join:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   // `select` needs to come after the call to `innerJoin` so\n   *   // that you can select from the joined table.\n   *   .select(['person.id', 'pet.name as pet_name'])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"id\", \"pet\".\"name\" as \"pet_name\"\n   * from \"person\"\n   * inner join \"pet\"\n   * on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ```\n   *\n   * <!-- siteExample(\"join\", \"Aliased inner join\", 20) -->\n   *\n   * You can give an alias for the joined table like this:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin('pet as p', 'p.owner_id', 'person.id')\n   *   .where('p.name', '=', 'Doggo')\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * inner join \"pet\" as \"p\"\n   * on \"p\".\"owner_id\" = \"person\".\"id\"\n   * where \"p\".name\" = $1\n   * ```\n   *\n   * <!-- siteExample(\"join\", \"Complex join\", 30) -->\n   *\n   * You can provide a function as the second argument to get a join\n   * builder for creating more complex joins. The join builder has a\n   * bunch of `on*` methods for building the `on` clause of the join.\n   * There's basically an equivalent for every `where` method\n   * (`on`, `onRef` etc.).\n   *\n   * You can do all the same things with the\n   * `on` method that you can with the corresponding `where` method (like [OR expressions for example](https://kysely.dev/docs/examples/WHERE/or-where)).\n   * See the `where` method documentation for more examples.\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin(\n   *     'pet',\n   *     (join) => join\n   *       .onRef('pet.owner_id', '=', 'person.id')\n   *       .on('pet.name', '=', 'Doggo')\n   *       .on((eb) => eb.or([\n   *         eb('person.age', '>', 18),\n   *         eb('person.age', '<', 100)\n   *       ]))\n   *   )\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * inner join \"pet\"\n   * on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * and \"pet\".\"name\" = $1\n   * and (\n   *   \"person\".\"age\" > $2\n   *   OR \"person\".\"age\" < $3\n   * )\n   * ```\n   *\n   * <!-- siteExample(\"join\", \"Subquery join\", 40) -->\n   *\n   * You can join a subquery by providing two callbacks:\n   *\n   * ```ts\n   * const result = await db.selectFrom('person')\n   *   .innerJoin(\n   *     (eb) => eb\n   *       .selectFrom('pet')\n   *       .select(['owner_id as owner', 'name'])\n   *       .where('name', '=', 'Doggo')\n   *       .as('doggos'),\n   *     (join) => join\n   *       .onRef('doggos.owner', '=', 'person.id'),\n   *   )\n   *   .selectAll('doggos')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"doggos\".*\n   * from \"person\"\n   * inner join (\n   *   select \"owner_id\" as \"owner\", \"name\"\n   *   from \"pet\"\n   *   where \"name\" = $1\n   * ) as \"doggos\"\n   * on \"doggos\".\"owner\" = \"person\".\"id\"\n   * ```\n   */\n  innerJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>\n\n  innerJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    callback: FN,\n  ): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>\n\n  /**\n   * Just like {@link innerJoin} but adds a `left join` instead of an `inner join`.\n   */\n  leftJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>\n\n  leftJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    callback: FN,\n  ): SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>\n\n  /**\n   * Just like {@link innerJoin} but adds a `right join` instead of an `inner join`.\n   */\n  rightJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): SelectQueryBuilderWithRightJoin<DB, TB, O, TE>\n\n  rightJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    callback: FN,\n  ): SelectQueryBuilderWithRightJoin<DB, TB, O, TE>\n\n  /**\n   * Just like {@link innerJoin} but adds a `full join` instead of an `inner join`.\n   *\n   * This is only supported by some dialects like PostgreSQL, MS SQL Server and SQLite.\n   */\n  fullJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): SelectQueryBuilderWithFullJoin<DB, TB, O, TE>\n\n  fullJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    callback: FN,\n  ): SelectQueryBuilderWithFullJoin<DB, TB, O, TE>\n\n  /**\n   * Just like {@link innerJoin} but adds a `cross join` instead of an `inner join`.\n   */\n  crossJoin<TE extends TableExpression<DB, TB>>(\n    table: TE,\n  ): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>\n\n  /**\n   * Just like {@link innerJoin} but adds a lateral join instead of an inner join.\n   *\n   * This is only supported by some dialects like PostgreSQL and MySQL.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoinLateral(\n   *     (eb) =>\n   *       eb.selectFrom('pet')\n   *         .select('name')\n   *         .whereRef('pet.owner_id', '=', 'person.id')\n   *         .as('p'),\n   *     (join) => join.onTrue()\n   *   )\n   *   .select(['first_name', 'p.name'])\n   *   .orderBy('first_name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"first_name\", \"p\".\"name\"\n   * from \"person\"\n   * inner join lateral (\n   *   select \"name\"\n   *   from \"pet\"\n   *   where \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ) as \"p\" on true\n   * order by \"first_name\"\n   * ```\n   */\n  innerJoinLateral<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>\n\n  innerJoinLateral<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    callback: FN,\n  ): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>\n\n  /**\n   * Just like {@link innerJoin} but adds a `left join lateral` instead of an `inner join`.\n   *\n   * This is only supported by some dialects like PostgreSQL and MySQL.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .leftJoinLateral(\n   *     (eb) =>\n   *       eb.selectFrom('pet')\n   *         .select('name')\n   *         .whereRef('pet.owner_id', '=', 'person.id')\n   *         .as('p'),\n   *     (join) => join.onTrue()\n   *   )\n   *   .select(['first_name', 'p.name'])\n   *   .orderBy('first_name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"first_name\", \"p\".\"name\"\n   * from \"person\"\n   * left join lateral (\n   *   select \"name\"\n   *   from \"pet\"\n   *   where \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ) as \"p\" on true\n   * order by \"first_name\"\n   * ```\n   */\n  leftJoinLateral<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>\n\n  leftJoinLateral<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    callback: FN,\n  ): SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>\n\n  /**\n   * Just like {@link innerJoin} but adds a `cross join lateral` instead of an `inner join`.\n   *\n   * This is only supported by some dialects like PostgreSQL.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .crossJoinLateral(\n   *     (eb) =>\n   *       eb.selectFrom('pet')\n   *         .select('name')\n   *         .whereRef('pet.owner_id', '=', 'person.id')\n   *         .as('p')\n   *   )\n   *   .select(['first_name', 'p.name'])\n   *   .orderBy('first_name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"first_name\", \"p\".\"name\"\n   * from \"person\"\n   * cross join lateral (\n   *   select \"name\"\n   *   from \"pet\"\n   *   where \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ) as \"p\"\n   * order by \"first_name\"\n   * ```\n   */\n  crossJoinLateral<TE extends TableExpression<DB, TB>>(\n    table: TE,\n  ): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>\n\n  /**\n   * Joins another table to the query using a `cross apply`.\n   *\n   * This is only supported by some dialects like MS SQL Server.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .crossApply(\n   *     (eb) =>\n   *       eb.selectFrom('pet')\n   *         .select('name')\n   *         .whereRef('pet.owner_id', '=', 'person.id')\n   *         .as('p')\n   *   )\n   *   .select(['first_name', 'p.name'])\n   *   .orderBy('first_name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * select \"person\".\"first_name\", \"p\".\"name\"\n   * from \"person\"\n   * cross apply (\n   *   select \"name\"\n   *   from \"pet\"\n   *   where \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ) as \"p\"\n   * order by \"first_name\"\n   * ```\n   */\n  crossApply<TE extends TableExpression<DB, TB>>(\n    table: TE,\n  ): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>\n\n  /**\n   * Just like {@link crossApply} but adds an `outer apply` instead of a `cross apply`.\n   *\n   * This is only supported by some dialects like MS SQL Server.\n   */\n  outerApply<TE extends TableExpression<DB, TB>>(\n    table: TE,\n  ): SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>\n\n  /**\n   * Adds a `group by` clause to the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db\n   *   .selectFrom('person')\n   *   .select([\n   *     'first_name',\n   *     sql<string>`max(id)`.as('max_id')\n   *   ])\n   *   .groupBy('first_name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\", max(id)\n   * from \"person\"\n   * group by \"first_name\"\n   * ```\n   *\n   * `groupBy` also accepts an array:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db\n   *   .selectFrom('person')\n   *   .select([\n   *     'first_name',\n   *     'last_name',\n   *     sql<string>`max(id)`.as('max_id')\n   *   ])\n   *   .groupBy([\n   *     'first_name',\n   *     'last_name'\n   *   ])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\", \"last_name\", max(id)\n   * from \"person\"\n   * group by \"first_name\", \"last_name\"\n   * ```\n   *\n   * The group by expressions can also be subqueries or\n   * raw sql expressions:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db\n   *   .selectFrom('person')\n   *   .select([\n   *     'first_name',\n   *     'last_name',\n   *     sql<string>`max(id)`.as('max_id')\n   *   ])\n   *   .groupBy([\n   *     sql<string>`concat(first_name, last_name)`,\n   *     (qb) => qb.selectFrom('pet').select('id').limit(1)\n   *   ])\n   *   .execute()\n   * ```\n   *\n   * `dynamic.ref` can be used to refer to columns not known at\n   * compile time:\n   *\n   * ```ts\n   * async function someQuery(groupBy: string) {\n   *   const { ref } = db.dynamic\n   *\n   *   return await db\n   *     .selectFrom('person')\n   *     .select('first_name')\n   *     .groupBy(ref(groupBy))\n   *     .execute()\n   * }\n   *\n   * someQuery('first_name')\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\"\n   * from \"person\"\n   * group by \"first_name\"\n   * ```\n   */\n  groupBy<GE extends GroupByArg<DB, TB, O>>(\n    groupBy: GE,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  orderBy<OE extends OrderByExpression<DB, TB, O>>(\n    expr: OE,\n    modifiers?: OrderByModifiers,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated It does ~2-2.5x more compile-time instantiations than multiple `orderBy(expr, modifiers?)` calls, and has broken autocompletion.\n   */\n  orderBy<\n    OE extends\n      | OrderByExpression<DB, TB, O>\n      | DirectedOrderByStringReference<DB, TB, O>,\n  >(\n    exprs: ReadonlyArray<OE>,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated Use orderBy(expr, direction) instead.\n   */\n  orderBy<OE extends DirectedOrderByStringReference<DB, TB, O>>(\n    expr: OE,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @deprecated Use `orderBy(expr, (ob) => ...)` instead.\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, O>>(\n    expr: OE,\n    modifiers: Expression<any>,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds a limit clause to the query.\n   *\n   * Passing a `null` value is only supported by some dialects like PostgreSQL,\n   * and will result in a no-op limit clause.\n   *\n   * ### Examples\n   *\n   * Select the first 10 rows of the result:\n   *\n   * ```ts\n   * await db\n   *   .selectFrom('person')\n   *   .select('first_name')\n   *   .limit(10)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\" from \"person\" limit $1\n   * ```\n   *\n   * Select rows from index 10 to index 19 of the result:\n   *\n   * ```ts\n   * await db\n   *   .selectFrom('person')\n   *   .select('first_name')\n   *   .limit(10)\n   *   .offset(10)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\" from \"person\" limit $1 offset $2\n   * ```\n   */\n  limit(\n    limit: ValueExpression<DB, TB, number | bigint | null>,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds an `offset` clause to the query.\n   *\n   * ### Examples\n   *\n   * Select rows from index 10 to index 19 of the result:\n   *\n   * ```ts\n   * await db\n   *   .selectFrom('person')\n   *   .select('first_name')\n   *   .limit(10)\n   *   .offset(10)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\" from \"person\" limit $1 offset $2\n   * ```\n   */\n  offset(\n    offset: ValueExpression<DB, TB, number | bigint>,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds a `fetch` clause to the query.\n   *\n   * This clause is only supported by some dialects like PostgreSQL or MS SQL Server.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db\n   *   .selectFrom('person')\n   *   .select('first_name')\n   *   .orderBy('first_name')\n   *   .offset(0)\n   *   .fetch(10)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * select \"first_name\"\n   * from \"person\"\n   * order by \"first_name\"\n   * offset 0 rows\n   * fetch next 10 rows only\n   * ```\n   */\n  fetch(\n    rowCount: number | bigint,\n    modifier?: FetchModifier,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Adds a `top` clause to the query.\n   *\n   * This clause is only supported by some dialects like MS SQL Server.\n   *\n   * ### Examples\n   *\n   * Select 10 biggest ages:\n   *\n   * ```ts\n   * await db\n   *   .selectFrom('person')\n   *   .select('age')\n   *   .top(10)\n   *   .orderBy('age desc')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * select top(10) \"age\" from \"person\" order by \"age\" desc\n   * ```\n   *\n   * Select 10% first rows:\n   *\n   * ```ts\n   * await db\n   *  .selectFrom('person')\n   *  .selectAll()\n   *  .top(10, 'percent')\n   *  .execute()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * select top(10) percent * from \"person\"\n   * ```\n   */\n  top(\n    expression: number | bigint,\n    modifiers?: TopModifier,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Combines another select query or raw expression to this query using `union`.\n   *\n   * The output row type of the combined query must match `this` query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .union(db.selectFrom('pet').select(['id', 'name']))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * union\n   * select \"id\", \"name\"\n   * from \"pet\"\n   * order by \"name\"\n   * ```\n   *\n   * You can provide a callback to get an expression builder.\n   * In the following example, this allows us to wrap the query in parentheses:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .union((eb) => eb.parens(\n   *     eb.selectFrom('pet').select(['id', 'name'])\n   *   ))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * union\n   * (\n   *   select \"id\", \"name\"\n   *   from \"pet\"\n   * )\n   * order by \"name\"\n   * ```\n   */\n  union<E extends SetOperandExpression<DB, O>>(\n    expression: E,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Combines another select query or raw expression to this query using `union all`.\n   *\n   * The output row type of the combined query must match `this` query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .unionAll(db.selectFrom('pet').select(['id', 'name']))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * union all\n   * select \"id\", \"name\"\n   * from \"pet\"\n   * order by \"name\"\n   * ```\n   *\n   * You can provide a callback to get an expression builder.\n   * In the following example, this allows us to wrap the query in parentheses:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .unionAll((eb) => eb.parens(\n   *     eb.selectFrom('pet').select(['id', 'name'])\n   *   ))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * union all\n   * (\n   *   select \"id\", \"name\"\n   *   from \"pet\"\n   * )\n   * order by \"name\"\n   * ```\n   */\n  unionAll<E extends SetOperandExpression<DB, O>>(\n    expression: E,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Combines another select query or raw expression to this query using `intersect`.\n   *\n   * The output row type of the combined query must match `this` query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .intersect(db.selectFrom('pet').select(['id', 'name']))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * intersect\n   * select \"id\", \"name\"\n   * from \"pet\"\n   * order by \"name\"\n   * ```\n   *\n   * You can provide a callback to get an expression builder.\n   * In the following example, this allows us to wrap the query in parentheses:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .intersect((eb) => eb.parens(\n   *     eb.selectFrom('pet').select(['id', 'name'])\n   *   ))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * intersect\n   * (\n   *   select \"id\", \"name\"\n   *   from \"pet\"\n   * )\n   * order by \"name\"\n   * ```\n   */\n  intersect<E extends SetOperandExpression<DB, O>>(\n    expression: E,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Combines another select query or raw expression to this query using `intersect all`.\n   *\n   * The output row type of the combined query must match `this` query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .intersectAll(db.selectFrom('pet').select(['id', 'name']))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * intersect all\n   * select \"id\", \"name\"\n   * from \"pet\"\n   * order by \"name\"\n   * ```\n   *\n   * You can provide a callback to get an expression builder.\n   * In the following example, this allows us to wrap the query in parentheses:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .intersectAll((eb) => eb.parens(\n   *     eb.selectFrom('pet').select(['id', 'name'])\n   *   ))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * intersect all\n   * (\n   *   select \"id\", \"name\"\n   *   from \"pet\"\n   * )\n   * order by \"name\"\n   * ```\n   */\n  intersectAll<E extends SetOperandExpression<DB, O>>(\n    expression: E,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Combines another select query or raw expression to this query using `except`.\n   *\n   * The output row type of the combined query must match `this` query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .except(db.selectFrom('pet').select(['id', 'name']))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * except\n   * select \"id\", \"name\"\n   * from \"pet\"\n   * order by \"name\"\n   * ```\n   *\n   * You can provide a callback to get an expression builder.\n   * In the following example, this allows us to wrap the query in parentheses:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .except((eb) => eb.parens(\n   *     eb.selectFrom('pet').select(['id', 'name'])\n   *   ))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * except\n   * (\n   *   select \"id\", \"name\"\n   *   from \"pet\"\n   * )\n   * order by \"name\"\n   * ```\n   */\n  except<E extends SetOperandExpression<DB, O>>(\n    expression: E,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Combines another select query or raw expression to this query using `except all`.\n   *\n   * The output row type of the combined query must match `this` query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .exceptAll(db.selectFrom('pet').select(['id', 'name']))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * except all\n   * select \"id\", \"name\"\n   * from \"pet\"\n   * order by \"name\"\n   * ```\n   *\n   * You can provide a callback to get an expression builder.\n   * In the following example, this allows us to wrap the query in parentheses:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name as name'])\n   *   .exceptAll((eb) => eb.parens(\n   *     eb.selectFrom('pet').select(['id', 'name'])\n   *   ))\n   *   .orderBy('name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"first_name\" as \"name\"\n   * from \"person\"\n   * except all\n   * (\n   *   select \"id\", \"name\"\n   *   from \"pet\"\n   * )\n   * order by \"name\"\n   * ```\n   */\n  exceptAll<E extends SetOperandExpression<DB, O>>(\n    expression: E,\n  ): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Gives an alias for the query. This method is only useful for sub queries.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const pets = await db.selectFrom('pet')\n   *   .selectAll('pet')\n   *   .select(\n   *     (qb) => qb.selectFrom('person')\n   *       .select('first_name')\n   *       .whereRef('pet.owner_id', '=', 'person.id')\n   *       .as('owner_first_name')\n   *   )\n   *   .execute()\n   *\n   * pets[0].owner_first_name\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"pet\".*, (\n   *   select \"first_name\"\n   *   from \"person\"\n   *   where \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ) as \"owner_first_name\"\n   * from \"pet\"\n   * ```\n   */\n  as<A extends string>(alias: A): AliasedSelectQueryBuilder<O, A>\n\n  /**\n   * Clears all select clauses from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .select(['id', 'first_name'])\n   *   .clearSelect()\n   *   .select(['id', 'gender'])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * select \"id\", \"gender\" from \"person\"\n   * ```\n   */\n  clearSelect(): SelectQueryBuilder<DB, TB, {}>\n\n  clearWhere(): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Clears limit clause from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .selectAll()\n   *   .limit(10)\n   *   .clearLimit()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\"\n   * ```\n   */\n  clearLimit(): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Clears offset clause from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .selectAll()\n   *   .limit(10)\n   *   .offset(20)\n   *   .clearOffset()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\" limit 10\n   * ```\n   */\n  clearOffset(): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Clears all `order by` clauses from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .selectAll()\n   *   .orderBy('id')\n   *   .clearOrderBy()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\"\n   * ```\n   */\n  clearOrderBy(): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Clears `group by` clause from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .selectAll()\n   *   .groupBy('id')\n   *   .clearGroupBy()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\"\n   * ```\n   */\n  clearGroupBy(): SelectQueryBuilder<DB, TB, O>\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   *\n   * If you want to conditionally call a method on `this`, see\n   * the {@link $if} method.\n   *\n   * ### Examples\n   *\n   * The next example uses a helper function `log` to log a query:\n   *\n   * ```ts\n   * import type { Compilable } from 'kysely'\n   *\n   * function log<T extends Compilable>(qb: T): T {\n   *   console.log(qb.compile())\n   *   return qb\n   * }\n   *\n   * await db.selectFrom('person')\n   *   .selectAll()\n   *   .$call(log)\n   *   .execute()\n   * ```\n   */\n  $call<T>(func: (qb: this) => T): T\n\n  /**\n   * Call `func(this)` if `condition` is true.\n   *\n   * NOTE: This method has an impact on TypeScript performance and it should only be used\n   * when necessary. Remember that you can call most methods like `where` conditionally\n   * like this:\n   *\n   * ```ts\n   * async function getPeople(firstName?: string, lastName?: string) {\n   *   let query = db.selectFrom('person').selectAll()\n   *\n   *   if (firstName) {\n   *     query = query.where('first_name', '=', firstName)\n   *   }\n   *\n   *   if (lastName) {\n   *     query = query.where('last_name', '=', lastName)\n   *   }\n   *\n   *   return await query.execute()\n   * }\n   * ```\n   *\n   * This method is mainly useful with optional selects. Any `select` or `selectAll`\n   * method called inside the callback add optional fields to the result type. This is\n   * because we can't know if those selections were actually made before running the code.\n   *\n   * Also see [this recipe](https://github.com/kysely-org/kysely/blob/master/site/docs/recipes/0005-conditional-selects.md)\n   *\n   * ### Examples\n   *\n   * ```ts\n   * async function getPerson(id: number, withLastName: boolean) {\n   *   return await db\n   *     .selectFrom('person')\n   *     .select(['id', 'first_name'])\n   *     .$if(withLastName, (qb) => qb.select('last_name'))\n   *     .where('id', '=', id)\n   *     .executeTakeFirstOrThrow()\n   * }\n   * ```\n   *\n   * Any selections added inside the `if` callback will be added as optional fields to the\n   * output type since we can't know if the selections were actually made before running\n   * the code. In the example above the return type of the `getPerson` function is:\n   *\n   * ```ts\n   * Promise<{\n   *   id: number\n   *   first_name: string\n   *   last_name?: string\n   * }>\n   * ```\n   *\n   * You can also call any other methods inside the callback:\n   *\n   * ```ts\n   * async function getPeople(firstName?: string, petCountLimit?: number) {\n   *   return await db.selectFrom('person')\n   *     .select('person.id')\n   *     .$if(firstName != null, (qb) => qb.where('first_name', '=', firstName!))\n   *     .$if(petCountLimit != null, (qb) => qb\n   *       .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *       .having((eb) => eb.fn.count('pet.id'), '>', petCountLimit!)\n   *       .groupBy('person.id')\n   *     )\n   *     .execute()\n   * }\n   * ```\n   */\n  $if<O2>(\n    condition: boolean,\n    func: (qb: this) => SelectQueryBuilder<any, any, O & O2>,\n  ): SelectQueryBuilder<DB, TB, O & Partial<Omit<O2, keyof O>>>\n\n  /**\n   * Change the output type of the query.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `SelectQueryBuilder` with a new output type.\n   */\n  $castTo<C>(): SelectQueryBuilder<DB, TB, C>\n\n  /**\n   * Changes the output type from an object to a tuple.\n   *\n   * This doesn't affect the generated SQL in any way. This function is\n   * just a necessary evil when you need to convert a query's output\n   * record type to a tuple type. Typescript doesn't currently offer\n   * tools to do this automatically (without insane hackery).\n   *\n   * The returned object can no longer be executed. It can only be used\n   * as a subquery.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .selectAll('person')\n   *   .where(({ eb, refTuple, selectFrom }) => eb(\n   *     refTuple('first_name', 'last_name'),\n   *     'in',\n   *     selectFrom('pet')\n   *       .select(['name', 'species'])\n   *       .where('pet.species', '!=', 'cat')\n   *       .$asTuple('name', 'species')\n   *   ))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * select\n   *   \"person\".*\n   * from\n   *   \"person\"\n   * where\n   *   (\"first_name\", \"last_name\")\n   *   in\n   *   (\n   *     select \"name\", \"species\"\n   *     from \"pet\"\n   *     where \"pet\".\"species\" != $1\n   *   )\n   * ```\n   */\n  $asTuple<K1 extends keyof O, K2 extends Exclude<keyof O, K1>>(\n    key1: K1,\n    key2: K2,\n  ): keyof O extends K1 | K2\n    ? ExpressionWrapper<DB, TB, [O[K1], O[K2]]>\n    : KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'>\n\n  $asTuple<\n    K1 extends keyof O,\n    K2 extends Exclude<keyof O, K1>,\n    K3 extends Exclude<keyof O, K1 | K2>,\n  >(\n    key1: K1,\n    key2: K2,\n    key3: K3,\n  ): keyof O extends K1 | K2 | K3\n    ? ExpressionWrapper<DB, TB, [O[K1], O[K2], O[K3]]>\n    : KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'>\n\n  $asTuple<\n    K1 extends keyof O,\n    K2 extends Exclude<keyof O, K1>,\n    K3 extends Exclude<keyof O, K1 | K2>,\n    K4 extends Exclude<keyof O, K1 | K2 | K3>,\n  >(\n    key1: K1,\n    key2: K2,\n    key3: K3,\n    key4: K4,\n  ): keyof O extends K1 | K2 | K3 | K4\n    ? ExpressionWrapper<DB, TB, [O[K1], O[K2], O[K3], O[K4]]>\n    : KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'>\n\n  $asTuple<\n    K1 extends keyof O,\n    K2 extends Exclude<keyof O, K1>,\n    K3 extends Exclude<keyof O, K1 | K2>,\n    K4 extends Exclude<keyof O, K1 | K2 | K3>,\n    K5 extends Exclude<keyof O, K1 | K2 | K3 | K4>,\n  >(\n    key1: K1,\n    key2: K2,\n    key3: K3,\n    key4: K4,\n    key5: K5,\n  ): keyof O extends K1 | K2 | K3 | K4 | K5\n    ? ExpressionWrapper<DB, TB, [O[K1], O[K2], O[K3], O[K4], O[K5]]>\n    : KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'>\n\n  /**\n   * Plucks the value type of the output record.\n   *\n   * In SQL, any record type that only has one column can be used as a scalar.\n   * For example a query like this works:\n   *\n   * ```sql\n   * select\n   *   id,\n   *   first_name\n   * from\n   *   person as p\n   * where\n   *   -- This is ok since the query only selects one row\n   *   -- and one column.\n   *  (select name from pet where pet.owner_id = p.id limit 1) = 'Doggo'\n   * ```\n   *\n   * In many cases Kysely handles this automatically and picks the correct\n   * scalar type instead of the record type, but sometimes you need to give\n   * Kysely a hint.\n   *\n   * One such case are custom helper functions that take `Expression<T>`\n   * instances as inputs:\n   *\n   * ```ts\n   * import type { Expression } from 'kysely'\n   *\n   * function doStuff(expr: Expression<string>) {\n   *   // ...\n   * }\n   *\n   * // Error! This is not ok because the expression type is\n   * // `{ first_name: string }` instead of `string`.\n   * // doStuff(db.selectFrom('person').select('first_name'))\n   *\n   * // Ok! This is ok since we've plucked the `string` type of the\n   * // only column in the output type.\n   * doStuff(db.selectFrom('person').select('first_name').$asScalar())\n   * ```\n   *\n   * This function has absolutely no effect on the generated SQL. It's\n   * purely a type-level helper.\n   *\n   * This method returns an `ExpressionWrapper` instead of a `SelectQueryBuilder`\n   * since the return value should only be used as a part of an expression\n   * and never executed as the main query.\n   */\n  $asScalar<K extends keyof O = keyof O>(): ExpressionWrapper<DB, TB, O[K]>\n\n  /**\n   * Narrows (parts of) the output type of the query.\n   *\n   * Kysely tries to be as type-safe as possible, but in some cases we have to make\n   * compromises for better maintainability and compilation performance. At present,\n   * Kysely doesn't narrow the output type of the query when using {@link where}, {@link having}\n   * or {@link JoinQueryBuilder.on}.\n   *\n   * This utility method is very useful for these situations, as it removes unncessary\n   * runtime assertion/guard code. Its input type is limited to the output type\n   * of the query, so you can't add a column that doesn't exist, or change a column's\n   * type to something that doesn't exist in its union type.\n   *\n   * ### Examples\n   *\n   * Turn this code:\n   *\n   * ```ts\n   * import type { Person } from 'type-editor' // imaginary module\n   *\n   * const person = await db.selectFrom('person')\n   *   .where('nullable_column', 'is not', null)\n   *   .selectAll()\n   *   .executeTakeFirstOrThrow()\n   *\n   * if (isWithNoNullValue(person)) {\n   *   functionThatExpectsPersonWithNonNullValue(person)\n   * }\n   *\n   * function isWithNoNullValue(person: Person): person is Person & { nullable_column: string } {\n   *   return person.nullable_column != null\n   * }\n   * ```\n   *\n   * Into this:\n   *\n   * ```ts\n   * import type { NotNull } from 'kysely'\n   *\n   * const person = await db.selectFrom('person')\n   *   .where('nullable_column', 'is not', null)\n   *   .selectAll()\n   *   .$narrowType<{ nullable_column: NotNull }>()\n   *   .executeTakeFirstOrThrow()\n   *\n   * functionThatExpectsPersonWithNonNullValue(person)\n   * ```\n   *\n   * Giving the explicit narrowed type (`string` in the example above) works fine for\n   * simple types. If the type is complex, for example a JSON column or a subquery,\n   * you can use the special `NotNull` type to make the column not null.\n   *\n   * ```ts\n   * import { NotNull } from 'kysely'\n   *\n   * const person = await db.selectFrom('person')\n   *   .where('nullable_column', 'is not', null)\n   *   .selectAll()\n   *   .$narrowType<{ nullable_column: NotNull }>()\n   *   .executeTakeFirstOrThrow()\n   *\n   * functionThatExpectsPersonWithNonNullValue(person)\n   * ```\n   */\n  $narrowType<T>(): SelectQueryBuilder<DB, TB, NarrowPartial<O, T>>\n\n  /**\n   * Asserts that query's output row type equals the given type `T`.\n   *\n   * This method can be used to simplify excessively complex types to make TypeScript happy\n   * and much faster.\n   *\n   * Kysely uses complex type magic to achieve its type safety. This complexity is sometimes too much\n   * for TypeScript and you get errors like this:\n   *\n   * ```\n   * error TS2589: Type instantiation is excessively deep and possibly infinite.\n   * ```\n   *\n   * In these case you can often use this method to help TypeScript a little bit. When you use this\n   * method to assert the output type of a query, Kysely can drop the complex output type that\n   * consists of multiple nested helper types and replace it with the simple asserted type.\n   *\n   * Using this method doesn't reduce type safety at all. You have to pass in a type that is\n   * structurally equal to the current type.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db\n   *   .with('first_and_last', (qb) => qb\n   *     .selectFrom('person')\n   *     .select(['first_name', 'last_name'])\n   *     .$assertType<{ first_name: string, last_name: string | null }>()\n   *   )\n   *   .with('age', (qb) => qb\n   *     .selectFrom('person')\n   *     .select('age')\n   *     .$assertType<{ age: number | null }>()\n   *   )\n   *   .selectFrom(['first_and_last', 'age'])\n   *   .selectAll()\n   *   .executeTakeFirstOrThrow()\n   * ```\n   */\n  $assertType<T extends O>(): O extends T\n    ? SelectQueryBuilder<DB, TB, T>\n    : KyselyTypeError<`$assertType() call failed: The type passed in is not equal to the output type of the query.`>\n\n  /**\n   * Returns a copy of this SelectQueryBuilder instance with the given plugin installed.\n   */\n  withPlugin(plugin: KyselyPlugin): SelectQueryBuilder<DB, TB, O>\n\n  toOperationNode(): SelectQueryNode\n\n  compile(): CompiledQuery<Simplify<O>>\n\n  /**\n   * Executes the query and returns an array of rows.\n   *\n   * Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.\n   */\n  execute(): Promise<Simplify<O>[]>\n\n  /**\n   * Executes the query and returns the first result or undefined if\n   * the query returned no result.\n   */\n  executeTakeFirst(): Promise<SimplifySingleResult<O>>\n\n  /**\n   * Executes the query and returns the first result or throws if\n   * the query returned no result.\n   *\n   * By default an instance of {@link NoResultError} is thrown, but you can\n   * provide a custom error class, or callback to throw a different\n   * error.\n   */\n  executeTakeFirstOrThrow(\n    errorConstructor?: NoResultErrorConstructor | ((node: QueryNode) => Error),\n  ): Promise<Simplify<O>>\n\n  stream(chunkSize?: number): AsyncIterableIterator<O>\n\n  explain<ER extends Record<string, any> = Record<string, any>>(\n    format?: ExplainFormat,\n    options?: Expression<any>,\n  ): Promise<ER[]>\n}\n\nclass SelectQueryBuilderImpl<\n  DB,\n  TB extends keyof DB,\n  O,\n> implements SelectQueryBuilder<DB, TB, O> {\n  readonly #props: SelectQueryBuilderProps\n\n  constructor(props: SelectQueryBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  get expressionType(): O | undefined {\n    return undefined\n  }\n\n  get isSelectQueryBuilder(): true {\n    return true\n  }\n\n  where(...args: any[]): any {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithWhere(\n        this.#props.queryNode,\n        parseValueBinaryOperationOrExpression(args),\n      ),\n    })\n  }\n\n  whereRef(\n    lhs: ReferenceExpression<DB, TB>,\n    op: ComparisonOperatorExpression,\n    rhs: ReferenceExpression<DB, TB>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithWhere(\n        this.#props.queryNode,\n        parseReferentialBinaryOperation(lhs, op, rhs),\n      ),\n    })\n  }\n\n  having(...args: any[]): any {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithHaving(\n        this.#props.queryNode,\n        parseValueBinaryOperationOrExpression(args),\n      ),\n    })\n  }\n\n  havingRef(\n    lhs: ReferenceExpression<DB, TB>,\n    op: ComparisonOperatorExpression,\n    rhs: ReferenceExpression<DB, TB>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithHaving(\n        this.#props.queryNode,\n        parseReferentialBinaryOperation(lhs, op, rhs),\n      ),\n    })\n  }\n\n  select<SE extends SelectExpression<DB, TB>>(\n    selection: SelectArg<DB, TB, SE>,\n  ): SelectQueryBuilder<DB, TB, O & Selection<DB, TB, SE>> {\n    return new SelectQueryBuilderImpl<DB, TB, O & Selection<DB, TB, SE>>({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithSelections(\n        this.#props.queryNode,\n        parseSelectArg(selection),\n      ),\n    })\n  }\n\n  distinctOn(selection: ReferenceExpressionOrList<DB, TB>): any {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithDistinctOn(\n        this.#props.queryNode,\n        parseReferenceExpressionOrList(selection),\n      ),\n    })\n  }\n\n  modifyFront(modifier: Expression<any>): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithFrontModifier(\n        this.#props.queryNode,\n        SelectModifierNode.createWithExpression(modifier.toOperationNode()),\n      ),\n    })\n  }\n\n  modifyEnd(modifier: Expression<any>): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        SelectModifierNode.createWithExpression(modifier.toOperationNode()),\n      ),\n    })\n  }\n\n  distinct(): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithFrontModifier(\n        this.#props.queryNode,\n        SelectModifierNode.create('Distinct'),\n      ),\n    })\n  }\n\n  forUpdate(of?: TableOrList<TB>): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        SelectModifierNode.create(\n          'ForUpdate',\n          of ? asArray(of).map(parseTable) : undefined,\n        ),\n      ),\n    })\n  }\n\n  forShare(of?: TableOrList<TB>): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        SelectModifierNode.create(\n          'ForShare',\n          of ? asArray(of).map(parseTable) : undefined,\n        ),\n      ),\n    })\n  }\n\n  forKeyShare(of?: TableOrList<TB>): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        SelectModifierNode.create(\n          'ForKeyShare',\n          of ? asArray(of).map(parseTable) : undefined,\n        ),\n      ),\n    })\n  }\n\n  forNoKeyUpdate(of?: TableOrList<TB>): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        SelectModifierNode.create(\n          'ForNoKeyUpdate',\n          of ? asArray(of).map(parseTable) : undefined,\n        ),\n      ),\n    })\n  }\n\n  skipLocked(): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        SelectModifierNode.create('SkipLocked'),\n      ),\n    })\n  }\n\n  noWait(): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        SelectModifierNode.create('NoWait'),\n      ),\n    })\n  }\n\n  selectAll(table?: any): any {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithSelections(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n\n  innerJoin(...args: any): any {\n    return this.#join('InnerJoin', args)\n  }\n\n  leftJoin(...args: any): any {\n    return this.#join('LeftJoin', args)\n  }\n\n  rightJoin(...args: any): any {\n    return this.#join('RightJoin', args)\n  }\n\n  fullJoin(...args: any): any {\n    return this.#join('FullJoin', args)\n  }\n\n  crossJoin(...args: any): any {\n    return this.#join('CrossJoin', args)\n  }\n\n  innerJoinLateral(...args: any): any {\n    return this.#join('LateralInnerJoin', args)\n  }\n\n  leftJoinLateral(...args: any): any {\n    return this.#join('LateralLeftJoin', args)\n  }\n\n  crossJoinLateral(...args: any): any {\n    return this.#join('LateralCrossJoin', args)\n  }\n\n  crossApply(...args: any): any {\n    return this.#join('CrossApply', args)\n  }\n\n  outerApply(...args: any[]): any {\n    return this.#join('OuterApply', args)\n  }\n\n  #join(joinType: JoinType, args: any[]): any {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithJoin(\n        this.#props.queryNode,\n        parseJoin(joinType, args),\n      ),\n    })\n  }\n\n  orderBy(...args: any[]): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOrderByItems(\n        this.#props.queryNode,\n        parseOrderBy(args),\n      ),\n    })\n  }\n\n  groupBy(groupBy: GroupByArg<DB, TB, O>): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithGroupByItems(\n        this.#props.queryNode,\n        parseGroupBy(groupBy),\n      ),\n    })\n  }\n\n  limit(\n    limit: ValueExpression<DB, TB, number | bigint | null>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithLimit(\n        this.#props.queryNode,\n        LimitNode.create(parseValueExpression(limit)),\n      ),\n    })\n  }\n\n  offset(\n    offset: ValueExpression<DB, TB, number | bigint>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithOffset(\n        this.#props.queryNode,\n        OffsetNode.create(parseValueExpression(offset)),\n      ),\n    })\n  }\n\n  fetch(\n    rowCount: number | bigint,\n    modifier: FetchModifier = 'only',\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithFetch(\n        this.#props.queryNode,\n        parseFetch(rowCount, modifier),\n      ),\n    })\n  }\n\n  top(\n    expression: number | bigint,\n    modifiers?: TopModifier,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithTop(\n        this.#props.queryNode,\n        parseTop(expression, modifiers),\n      ),\n    })\n  }\n\n  union(\n    expression: SetOperandExpression<DB, O>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithSetOperations(\n        this.#props.queryNode,\n        parseSetOperations('union', expression, false),\n      ),\n    })\n  }\n\n  unionAll(\n    expression: SetOperandExpression<DB, O>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithSetOperations(\n        this.#props.queryNode,\n        parseSetOperations('union', expression, true),\n      ),\n    })\n  }\n\n  intersect(\n    expression: SetOperandExpression<DB, O>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithSetOperations(\n        this.#props.queryNode,\n        parseSetOperations('intersect', expression, false),\n      ),\n    })\n  }\n\n  intersectAll(\n    expression: SetOperandExpression<DB, O>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithSetOperations(\n        this.#props.queryNode,\n        parseSetOperations('intersect', expression, true),\n      ),\n    })\n  }\n\n  except(\n    expression: SetOperandExpression<DB, O>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithSetOperations(\n        this.#props.queryNode,\n        parseSetOperations('except', expression, false),\n      ),\n    })\n  }\n\n  exceptAll(\n    expression: SetOperandExpression<DB, O>,\n  ): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithSetOperations(\n        this.#props.queryNode,\n        parseSetOperations('except', expression, true),\n      ),\n    })\n  }\n\n  as<A extends string>(alias: A): AliasedSelectQueryBuilder<O, A> {\n    return new AliasedSelectQueryBuilderImpl(this, alias)\n  }\n\n  clearSelect(): SelectQueryBuilder<DB, TB, {}> {\n    return new SelectQueryBuilderImpl<DB, TB, {}>({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithoutSelections(this.#props.queryNode),\n    })\n  }\n\n  clearWhere(): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl<DB, TB, O>({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithoutWhere(this.#props.queryNode),\n    })\n  }\n\n  clearLimit(): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl<DB, TB, O>({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithoutLimit(this.#props.queryNode),\n    })\n  }\n\n  clearOffset(): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl<DB, TB, O>({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithoutOffset(this.#props.queryNode),\n    })\n  }\n\n  clearOrderBy(): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl<DB, TB, O>({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithoutOrderBy(this.#props.queryNode),\n    })\n  }\n\n  clearGroupBy(): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl<DB, TB, O>({\n      ...this.#props,\n      queryNode: SelectQueryNode.cloneWithoutGroupBy(this.#props.queryNode),\n    })\n  }\n\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  $if<O2>(\n    condition: boolean,\n    func: (qb: this) => SelectQueryBuilder<any, any, O & O2>,\n  ): SelectQueryBuilder<DB, TB, O & Partial<Omit<O2, keyof O>>> {\n    if (condition) {\n      return func(this)\n    }\n\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n    }) as any\n  }\n\n  $castTo<C>(): SelectQueryBuilder<DB, TB, C> {\n    return new SelectQueryBuilderImpl(this.#props)\n  }\n\n  $narrowType<T>(): SelectQueryBuilder<DB, TB, NarrowPartial<O, T>> {\n    return new SelectQueryBuilderImpl(this.#props)\n  }\n\n  $assertType<T extends O>(): O extends T\n    ? SelectQueryBuilder<DB, TB, T>\n    : KyselyTypeError<`$assertType() call failed: The type passed in is not equal to the output type of the query.`> {\n    return new SelectQueryBuilderImpl(this.#props) as unknown as any\n  }\n\n  $asTuple(): ExpressionWrapper<DB, TB, any> {\n    return new ExpressionWrapper(this.toOperationNode())\n  }\n\n  $asScalar(): ExpressionWrapper<DB, TB, any> {\n    return new ExpressionWrapper(this.toOperationNode())\n  }\n\n  withPlugin(plugin: KyselyPlugin): SelectQueryBuilder<DB, TB, O> {\n    return new SelectQueryBuilderImpl({\n      ...this.#props,\n      executor: this.#props.executor.withPlugin(plugin),\n    })\n  }\n\n  toOperationNode(): SelectQueryNode {\n    return this.#props.executor.transformQuery(\n      this.#props.queryNode,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery<Simplify<O>> {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<Simplify<O>[]> {\n    const compiledQuery = this.compile()\n\n    const result = await this.#props.executor.executeQuery<O>(compiledQuery)\n\n    return result.rows\n  }\n\n  async executeTakeFirst(): Promise<SimplifySingleResult<O>> {\n    const [result] = await this.execute()\n    return result as SimplifySingleResult<O>\n  }\n\n  async executeTakeFirstOrThrow(\n    errorConstructor:\n      | NoResultErrorConstructor\n      | ((node: QueryNode) => Error) = NoResultError,\n  ): Promise<Simplify<O>> {\n    const result = await this.executeTakeFirst()\n\n    if (result === undefined) {\n      const error = isNoResultErrorConstructor(errorConstructor)\n        ? new errorConstructor(this.toOperationNode())\n        : errorConstructor(this.toOperationNode())\n\n      throw error\n    }\n\n    return result as O\n  }\n\n  async *stream(chunkSize: number = 100): AsyncIterableIterator<O> {\n    const compiledQuery = this.compile()\n\n    const stream = this.#props.executor.stream<O>(compiledQuery, chunkSize)\n\n    for await (const item of stream) {\n      yield* item.rows\n    }\n  }\n\n  async explain<ER extends Record<string, any> = Record<string, any>>(\n    format?: ExplainFormat,\n    options?: Expression<any>,\n  ): Promise<ER[]> {\n    const builder = new SelectQueryBuilderImpl<DB, TB, ER>({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithExplain(\n        this.#props.queryNode,\n        format,\n        options,\n      ),\n    })\n\n    return await builder.execute()\n  }\n}\n\nexport function createSelectQueryBuilder<DB, TB extends keyof DB, O>(\n  props: SelectQueryBuilderProps,\n): SelectQueryBuilder<DB, TB, O> {\n  return new SelectQueryBuilderImpl(props)\n}\n\nexport interface SelectQueryBuilderProps {\n  readonly queryId: QueryId\n  readonly queryNode: SelectQueryNode\n  readonly executor: QueryExecutor\n}\n\nexport interface AliasedSelectQueryBuilder<\n  O = undefined,\n  A extends string = never,\n> extends AliasedExpression<O, A> {\n  get isAliasedSelectQueryBuilder(): true\n}\n\n/**\n * {@link SelectQueryBuilder} with an alias. The result of calling {@link SelectQueryBuilder.as}.\n */\nclass AliasedSelectQueryBuilderImpl<\n  DB,\n  TB extends keyof DB,\n  O = undefined,\n  A extends string = never,\n> implements AliasedSelectQueryBuilder<O, A> {\n  readonly #queryBuilder: SelectQueryBuilder<DB, TB, O>\n  readonly #alias: A\n\n  constructor(queryBuilder: SelectQueryBuilder<DB, TB, O>, alias: A) {\n    this.#queryBuilder = queryBuilder\n    this.#alias = alias\n  }\n\n  get expression(): Expression<O> {\n    return this.#queryBuilder\n  }\n\n  get alias(): A {\n    return this.#alias\n  }\n\n  get isAliasedSelectQueryBuilder(): true {\n    return true\n  }\n\n  toOperationNode(): AliasNode {\n    return AliasNode.create(\n      this.#queryBuilder.toOperationNode(),\n      IdentifierNode.create(this.#alias),\n    )\n  }\n}\n\nexport type SelectQueryBuilderWithInnerJoin<\n  DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? InnerJoinedBuilder<DB, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? SelectQueryBuilder<DB, TB | TE, O>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? InnerJoinedBuilder<DB, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? InnerJoinedBuilder<DB, TB, O, QA, QO>\n        : never\n\ntype InnerJoinedBuilder<\n  DB,\n  TB extends keyof DB,\n  O,\n  A extends string,\n  R,\n> = A extends keyof DB\n  ? SelectQueryBuilder<InnerJoinedDB<DB, A, R>, TB | A, O>\n  : // Much faster non-recursive solution for the simple case.\n    SelectQueryBuilder<DB & ShallowRecord<A, R>, TB | A, O>\n\ntype InnerJoinedDB<DB, A extends string, R> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A ? R : C extends keyof DB ? DB[C] : never\n}>\n\nexport type SelectQueryBuilderWithLeftJoin<\n  DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? LeftJoinedBuilder<DB, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? LeftJoinedBuilder<DB, TB, O, TE, DB[TE]>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? LeftJoinedBuilder<DB, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? LeftJoinedBuilder<DB, TB, O, QA, QO>\n        : never\n\ntype LeftJoinedBuilder<\n  DB,\n  TB extends keyof DB,\n  O,\n  A extends keyof any,\n  R,\n> = A extends keyof DB\n  ? SelectQueryBuilder<LeftJoinedDB<DB, A, R>, TB | A, O>\n  : // Much faster non-recursive solution for the simple case.\n    SelectQueryBuilder<DB & ShallowRecord<A, Nullable<R>>, TB | A, O>\n\ntype LeftJoinedDB<DB, A extends keyof any, R> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A\n    ? Nullable<R>\n    : C extends keyof DB\n      ? DB[C]\n      : never\n}>\n\nexport type SelectQueryBuilderWithRightJoin<\n  DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? RightJoinedBuilder<DB, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? RightJoinedBuilder<DB, TB, O, TE, DB[TE]>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? RightJoinedBuilder<DB, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? RightJoinedBuilder<DB, TB, O, QA, QO>\n        : never\n\ntype RightJoinedBuilder<\n  DB,\n  TB extends keyof DB,\n  O,\n  A extends keyof any,\n  R,\n> = SelectQueryBuilder<RightJoinedDB<DB, TB, A, R>, TB | A, O>\n\ntype RightJoinedDB<\n  DB,\n  TB extends keyof DB,\n  A extends keyof any,\n  R,\n> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A\n    ? R\n    : C extends TB\n      ? Nullable<DB[C]>\n      : C extends keyof DB\n        ? DB[C]\n        : never\n}>\n\nexport type SelectQueryBuilderWithFullJoin<\n  DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? OuterJoinedBuilder<DB, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? OuterJoinedBuilder<DB, TB, O, TE, DB[TE]>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? OuterJoinedBuilder<DB, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? OuterJoinedBuilder<DB, TB, O, QA, QO>\n        : never\n\ntype OuterJoinedBuilder<\n  DB,\n  TB extends keyof DB,\n  O,\n  A extends keyof any,\n  R,\n> = SelectQueryBuilder<OuterJoinedBuilderDB<DB, TB, A, R>, TB | A, O>\n\ntype OuterJoinedBuilderDB<\n  DB,\n  TB extends keyof DB,\n  A extends keyof any,\n  R,\n> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A\n    ? Nullable<R>\n    : C extends TB\n      ? Nullable<DB[C]>\n      : C extends keyof DB\n        ? DB[C]\n        : never\n}>\n\ntype TableOrList<TB extends keyof any> =\n  | (TB & string)\n  | ReadonlyArray<TB & string>\n"
  },
  {
    "path": "src/query-builder/update-query-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport {\n  type JoinCallbackExpression,\n  type JoinReferenceExpression,\n  parseJoin,\n} from '../parser/join-parser.js'\nimport {\n  type TableExpression,\n  type From,\n  type FromTables,\n  parseTableExpressionOrList,\n  type TableExpressionOrList,\n} from '../parser/table-parser.js'\nimport {\n  parseSelectArg,\n  parseSelectAll,\n  type SelectExpression,\n  type SelectArg,\n  type SelectCallback,\n} from '../parser/select-parser.js'\nimport type {\n  ReturningAllRow,\n  ReturningCallbackRow,\n  ReturningRow,\n} from '../parser/returning-parser.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport { QueryNode } from '../operation-node/query-node.js'\nimport type {\n  DrainOuterGeneric,\n  NarrowPartial,\n  Nullable,\n  ShallowRecord,\n  SimplifyResult,\n  SimplifySingleResult,\n  SqlBool,\n} from '../util/type-utils.js'\nimport { UpdateQueryNode } from '../operation-node/update-query-node.js'\nimport {\n  type UpdateObjectExpression,\n  type ExtractUpdateTypeFromReferenceExpression,\n  parseUpdate,\n} from '../parser/update-set-parser.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\nimport { UpdateResult } from './update-result.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport type { WhereInterface } from './where-interface.js'\nimport type { MultiTableReturningInterface } from './returning-interface.js'\nimport {\n  isNoResultErrorConstructor,\n  NoResultError,\n  type NoResultErrorConstructor,\n} from './no-result-error.js'\nimport type { Explainable, ExplainFormat } from '../util/explainable.js'\nimport type { AliasedExpression, Expression } from '../expression/expression.js'\nimport {\n  type ComparisonOperatorExpression,\n  type OperandValueExpressionOrList,\n  parseReferentialBinaryOperation,\n  parseValueBinaryOperationOrExpression,\n} from '../parser/binary-operation-parser.js'\nimport type { KyselyTypeError } from '../util/type-error.js'\nimport type { Streamable } from '../util/streamable.js'\nimport type { ExpressionOrFactory } from '../parser/expression-parser.js'\nimport {\n  type ValueExpression,\n  parseValueExpression,\n} from '../parser/value-parser.js'\nimport { LimitNode } from '../operation-node/limit-node.js'\nimport { parseTop } from '../parser/top-parser.js'\nimport type {\n  OutputCallback,\n  OutputExpression,\n  OutputInterface,\n  OutputPrefix,\n  SelectExpressionFromOutputCallback,\n  SelectExpressionFromOutputExpression,\n} from './output-interface.js'\nimport type { JoinType } from '../operation-node/join-node.js'\nimport type { OrderByInterface } from './order-by-interface.js'\nimport {\n  type DirectedOrderByStringReference,\n  type OrderByExpression,\n  type OrderByModifiers,\n  parseOrderBy,\n} from '../parser/order-by-parser.js'\n\nexport class UpdateQueryBuilder<DB, UT extends keyof DB, TB extends keyof DB, O>\n  implements\n    WhereInterface<DB, TB>,\n    MultiTableReturningInterface<DB, TB, O>,\n    OutputInterface<DB, TB, O>,\n    OrderByInterface<DB, TB, never>,\n    OperationNodeSource,\n    Compilable<O>,\n    Explainable,\n    Streamable<O>\n{\n  readonly #props: UpdateQueryBuilderProps\n\n  constructor(props: UpdateQueryBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  where<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): UpdateQueryBuilder<DB, UT, TB, O>\n\n  where<E extends ExpressionOrFactory<DB, TB, SqlBool>>(\n    expression: E,\n  ): UpdateQueryBuilder<DB, UT, TB, O>\n\n  where(...args: any[]): any {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithWhere(\n        this.#props.queryNode,\n        parseValueBinaryOperationOrExpression(args),\n      ),\n    })\n  }\n\n  whereRef<\n    LRE extends ReferenceExpression<DB, TB>,\n    RRE extends ReferenceExpression<DB, TB>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): UpdateQueryBuilder<DB, UT, TB, O> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithWhere(\n        this.#props.queryNode,\n        parseReferentialBinaryOperation(lhs, op, rhs),\n      ),\n    })\n  }\n\n  clearWhere(): UpdateQueryBuilder<DB, UT, TB, O> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithoutWhere(this.#props.queryNode),\n    })\n  }\n\n  /**\n   * Changes an `update` query into a `update top` query.\n   *\n   * `top` clause is only supported by some dialects like MS SQL Server.\n   *\n   * ### Examples\n   *\n   * Update the first row:\n   *\n   * ```ts\n   * await db.updateTable('person')\n   *   .top(1)\n   *   .set({ first_name: 'Foo' })\n   *   .where('age', '>', 18)\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * update top(1) \"person\" set \"first_name\" = @1 where \"age\" > @2\n   * ```\n   *\n   * Update the 50% first rows:\n   *\n   * ```ts\n   * await db.updateTable('person')\n   *   .top(50, 'percent')\n   *   .set({ first_name: 'Foo' })\n   *   .where('age', '>', 18)\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (MS SQL Server):\n   *\n   * ```sql\n   * update top(50) percent \"person\" set \"first_name\" = @1 where \"age\" > @2\n   * ```\n   */\n  top(\n    expression: number | bigint,\n    modifiers?: 'percent',\n  ): UpdateQueryBuilder<DB, UT, TB, O> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithTop(\n        this.#props.queryNode,\n        parseTop(expression, modifiers),\n      ),\n    })\n  }\n\n  /**\n   * Adds a from clause to the update query.\n   *\n   * This is supported only on some databases like PostgreSQL.\n   *\n   * The API is the same as {@link QueryCreator.selectFrom}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * db.updateTable('person')\n   *   .from('pet')\n   *   .set((eb) => ({\n   *     first_name: eb.ref('pet.name')\n   *   }))\n   *   .whereRef('pet.owner_id', '=', 'person.id')\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * update \"person\"\n   * set \"first_name\" = \"pet\".\"name\"\n   * from \"pet\"\n   * where \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ```\n   */\n  from<TE extends TableExpression<DB, TB>>(\n    table: TE,\n  ): UpdateQueryBuilder<From<DB, TE>, UT, FromTables<DB, TB, TE>, O>\n\n  from<TE extends TableExpression<DB, TB>>(\n    table: TE[],\n  ): UpdateQueryBuilder<From<DB, TE>, UT, FromTables<DB, TB, TE>, O>\n\n  from(from: TableExpressionOrList<any, any>): any {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: UpdateQueryNode.cloneWithFromItems(\n        this.#props.queryNode,\n        parseTableExpressionOrList(from),\n      ),\n    })\n  }\n\n  /**\n   * Joins another table to the query using an inner join.\n   *\n   * ### Examples\n   *\n   * Simple usage by providing a table name and two columns to join:\n   *\n   * ```ts\n   * const result = await db\n   *   .selectFrom('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   // `select` needs to come after the call to `innerJoin` so\n   *   // that you can select from the joined table.\n   *   .select(['person.id', 'pet.name'])\n   *   .execute()\n   *\n   * result[0].id\n   * result[0].name\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"id\", \"pet\".\"name\"\n   * from \"person\"\n   * inner join \"pet\"\n   * on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * ```\n   *\n   * You can give an alias for the joined table like this:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin('pet as p', 'p.owner_id', 'person.id')\n   *   .where('p.name', '=', 'Doggo')\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * inner join \"pet\" as \"p\"\n   * on \"p\".\"owner_id\" = \"person\".\"id\"\n   * where \"p\".name\" = $1\n   * ```\n   *\n   * You can provide a function as the second argument to get a join\n   * builder for creating more complex joins. The join builder has a\n   * bunch of `on*` methods for building the `on` clause of the join.\n   * There's basically an equivalent for every `where` method\n   * (`on`, `onRef`, `onExists` etc.). You can do all the same things\n   * with the `on` method that you can with the corresponding `where`\n   * method. See the `where` method documentation for more examples.\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin(\n   *     'pet',\n   *     (join) => join\n   *       .onRef('pet.owner_id', '=', 'person.id')\n   *       .on('pet.name', '=', 'Doggo')\n   *   )\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * inner join \"pet\"\n   * on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * and \"pet\".\"name\" = $1\n   * ```\n   *\n   * You can join a subquery by providing a select query (or a callback)\n   * as the first argument:\n   *\n   * ```ts\n   * await db.selectFrom('person')\n   *   .innerJoin(\n   *     db.selectFrom('pet')\n   *       .select(['owner_id', 'name'])\n   *       .where('name', '=', 'Doggo')\n   *       .as('doggos'),\n   *     'doggos.owner_id',\n   *     'person.id',\n   *   )\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * inner join (\n   *   select \"owner_id\", \"name\"\n   *   from \"pet\"\n   *   where \"name\" = $1\n   * ) as \"doggos\"\n   * on \"doggos\".\"owner_id\" = \"person\".\"id\"\n   * ```\n   */\n  innerJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): UpdateQueryBuilderWithInnerJoin<DB, UT, TB, O, TE>\n\n  innerJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(table: TE, callback: FN): UpdateQueryBuilderWithInnerJoin<DB, UT, TB, O, TE>\n\n  innerJoin(...args: any): any {\n    return this.#join('InnerJoin', args)\n  }\n\n  /**\n   * Just like {@link innerJoin} but adds a left join instead of an inner join.\n   */\n  leftJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): UpdateQueryBuilderWithLeftJoin<DB, UT, TB, O, TE>\n\n  leftJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(table: TE, callback: FN): UpdateQueryBuilderWithLeftJoin<DB, UT, TB, O, TE>\n\n  leftJoin(...args: any): any {\n    return this.#join('LeftJoin', args)\n  }\n\n  /**\n   * Just like {@link innerJoin} but adds a right join instead of an inner join.\n   */\n  rightJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): UpdateQueryBuilderWithRightJoin<DB, UT, TB, O, TE>\n\n  rightJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(table: TE, callback: FN): UpdateQueryBuilderWithRightJoin<DB, UT, TB, O, TE>\n\n  rightJoin(...args: any): any {\n    return this.#join('RightJoin', args)\n  }\n\n  /**\n   * Just like {@link innerJoin} but adds a full join instead of an inner join.\n   */\n  fullJoin<\n    TE extends TableExpression<DB, TB>,\n    K1 extends JoinReferenceExpression<DB, TB, TE>,\n    K2 extends JoinReferenceExpression<DB, TB, TE>,\n  >(\n    table: TE,\n    k1: K1,\n    k2: K2,\n  ): UpdateQueryBuilderWithFullJoin<DB, UT, TB, O, TE>\n\n  fullJoin<\n    TE extends TableExpression<DB, TB>,\n    FN extends JoinCallbackExpression<DB, TB, TE>,\n  >(table: TE, callback: FN): UpdateQueryBuilderWithFullJoin<DB, UT, TB, O, TE>\n\n  fullJoin(...args: any): any {\n    return this.#join('FullJoin', args)\n  }\n\n  #join(joinType: JoinType, args: any[]): any {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithJoin(\n        this.#props.queryNode,\n        parseJoin(joinType, args),\n      ),\n    })\n  }\n\n  /**\n   * @description This is only supported by some dialects like MySQL or SQLite with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`.\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers?: OrderByModifiers,\n  ): UpdateQueryBuilder<DB, UT, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @description This is only supported by some dialects like MySQL or SQLite with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`.\n   * @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `orderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.\n   */\n  orderBy<\n    OE extends\n      | OrderByExpression<DB, TB, {}>\n      | DirectedOrderByStringReference<DB, TB, {}>,\n  >(exprs: ReadonlyArray<OE>): UpdateQueryBuilder<DB, UT, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @description This is only supported by some dialects like MySQL or SQLite with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`.\n   * @deprecated It does ~2.9x more compile-time instantiations compared to a `orderBy(expr, direction)` call.\n   */\n  orderBy<OE extends DirectedOrderByStringReference<DB, TB, {}>>(\n    expr: OE,\n  ): UpdateQueryBuilder<DB, UT, TB, O>\n\n  // TODO: remove in v0.29\n  /**\n   * @description This is only supported by some dialects like MySQL or SQLite with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`.\n   * @deprecated Use `orderBy(expr, (ob) => ...)` instead.\n   */\n  orderBy<OE extends OrderByExpression<DB, TB, {}>>(\n    expr: OE,\n    modifiers: Expression<any>,\n  ): UpdateQueryBuilder<DB, UT, TB, O>\n\n  orderBy(...args: any[]): any {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOrderByItems(\n        this.#props.queryNode,\n        parseOrderBy(args),\n      ),\n    })\n  }\n\n  clearOrderBy(): UpdateQueryBuilder<DB, UT, TB, O> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithoutOrderBy(this.#props.queryNode),\n    })\n  }\n\n  /**\n   * Adds a limit clause to the update query for supported databases, such as MySQL.\n   *\n   * ### Examples\n   *\n   * Update the first 2 rows in the 'person' table:\n   *\n   * ```ts\n   * await db\n   *   .updateTable('person')\n   *   .set({ first_name: 'Foo' })\n   *   .limit(2)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * update `person` set `first_name` = ? limit ?\n   * ```\n   */\n  limit(\n    limit: ValueExpression<DB, TB, number>,\n  ): UpdateQueryBuilder<DB, UT, TB, O> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: UpdateQueryNode.cloneWithLimit(\n        this.#props.queryNode,\n        LimitNode.create(parseValueExpression(limit)),\n      ),\n    })\n  }\n\n  /**\n   * Sets the values to update for an {@link Kysely.updateTable | update} query.\n   *\n   * This method takes an object whose keys are column names and values are\n   * values to update. In addition to the column's type, the values can be\n   * any expressions such as raw {@link sql} snippets or select queries.\n   *\n   * This method also accepts a callback that returns the update object. The\n   * callback takes an instance of {@link ExpressionBuilder} as its only argument.\n   * The expression builder can be used to create arbitrary update expressions.\n   *\n   * The return value of an update query is an instance of {@link UpdateResult}.\n   * You can use the {@link returning} method on supported databases to get out\n   * the updated rows.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"update\", \"Single row\", 10) -->\n   *\n   * Update a row in `person` table:\n   *\n   * ```ts\n   * const result = await db\n   *   .updateTable('person')\n   *   .set({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   })\n   *   .where('id', '=', 1)\n   *   .executeTakeFirst()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * update \"person\" set \"first_name\" = $1, \"last_name\" = $2 where \"id\" = $3\n   * ```\n   *\n   * <!-- siteExample(\"update\", \"Complex values\", 20) -->\n   *\n   * As always, you can provide a callback to the `set` method to get access\n   * to an expression builder:\n   *\n   * ```ts\n   * const result = await db\n   *   .updateTable('person')\n   *   .set((eb) => ({\n   *     age: eb('age', '+', 1),\n   *     first_name: eb.selectFrom('pet').select('name').limit(1),\n   *     last_name: 'updated',\n   *   }))\n   *   .where('id', '=', 1)\n   *   .executeTakeFirst()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * update \"person\"\n   * set\n   *   \"first_name\" = (select \"name\" from \"pet\" limit $1),\n   *   \"age\" = \"age\" + $2,\n   *   \"last_name\" = $3\n   * where\n   *   \"id\" = $4\n   * ```\n   *\n   * If you provide two arguments the first one is interpreted as the column\n   * (or other target) and the second as the value:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const result = await db\n   *   .updateTable('person')\n   *   .set('first_name', 'Foo')\n   *   // As always, both arguments can be arbitrary expressions or\n   *   // callbacks that give you access to an expression builder:\n   *   .set(sql<string>`address['postalCode']`, (eb) => eb.val('61710'))\n   *   .where('id', '=', 1)\n   *   .executeTakeFirst()\n   * ```\n   *\n   * On PostgreSQL you can chain `returning` to the query to get\n   * the updated rows' columns (or any other expression) as the\n   * return value:\n   *\n   * ```ts\n   * const row = await db\n   *   .updateTable('person')\n   *   .set({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   })\n   *   .where('id', '=', 1)\n   *   .returning('id')\n   *   .executeTakeFirstOrThrow()\n   *\n   * row.id\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * update \"person\" set \"first_name\" = $1, \"last_name\" = $2 where \"id\" = $3 returning \"id\"\n   * ```\n   *\n   * In addition to primitives, the values can arbitrary expressions including\n   * raw `sql` snippets or subqueries:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const result = await db\n   *   .updateTable('person')\n   *   .set(({ selectFrom, ref, fn, eb }) => ({\n   *     first_name: selectFrom('person').select('first_name').limit(1),\n   *     middle_name: ref('first_name'),\n   *     age: eb('age', '+', 1),\n   *     last_name: sql<string>`${'Ani'} || ${'ston'}`,\n   *   }))\n   *   .where('id', '=', 1)\n   *   .executeTakeFirst()\n   *\n   * console.log(result.numUpdatedRows)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * update \"person\" set\n   * \"first_name\" = (select \"first_name\" from \"person\" limit $1),\n   * \"middle_name\" = \"first_name\",\n   * \"age\" = \"age\" + $2,\n   * \"last_name\" = $3 || $4\n   * where \"id\" = $5\n   * ```\n   *\n   * <!-- siteExample(\"update\", \"MySQL joins\", 30) -->\n   *\n   * MySQL allows you to join tables directly to the \"main\" table and update\n   * rows of all joined tables. This is possible by passing all tables to the\n   * `updateTable` method as a list and adding the `ON` conditions as `WHERE`\n   * statements. You can then use the `set(column, value)` variant to update\n   * columns using table qualified names.\n   *\n   * The `UpdateQueryBuilder` also has `innerJoin` etc. join methods, but those\n   * can only be used as part of a PostgreSQL `update set from join` query.\n   * Due to type complexity issues, we unfortunately can't make the same\n   * methods work in both cases.\n   *\n   * ```ts\n   * const result = await db\n   *   .updateTable(['person', 'pet'])\n   *   .set('person.first_name', 'Updated person')\n   *   .set('pet.name', 'Updated doggo')\n   *   .whereRef('person.id', '=', 'pet.owner_id')\n   *   .where('person.id', '=', 1)\n   *   .executeTakeFirst()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * update\n   *   `person`,\n   *   `pet`\n   * set\n   *   `person`.`first_name` = ?,\n   *   `pet`.`name` = ?\n   * where\n   *   `person`.`id` = `pet`.`owner_id`\n   *   and `person`.`id` = ?\n   * ```\n   */\n  set(\n    update: UpdateObjectExpression<DB, TB, UT>,\n  ): UpdateQueryBuilder<DB, UT, TB, O>\n\n  set<RE extends ReferenceExpression<DB, UT>>(\n    key: RE,\n    value: ValueExpression<\n      DB,\n      TB,\n      ExtractUpdateTypeFromReferenceExpression<DB, UT, RE>\n    >,\n  ): UpdateQueryBuilder<DB, UT, TB, O>\n\n  set(\n    ...args:\n      | [UpdateObjectExpression<DB, TB, UT>]\n      | [ReferenceExpression<DB, UT>, ValueExpression<DB, UT, unknown>]\n  ): UpdateQueryBuilder<DB, UT, TB, O> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: UpdateQueryNode.cloneWithUpdates(\n        this.#props.queryNode,\n        parseUpdate(...args),\n      ),\n    })\n  }\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selections: ReadonlyArray<SE>,\n  ): UpdateQueryBuilder<DB, UT, TB, ReturningRow<DB, TB, O, SE>>\n\n  returning<CB extends SelectCallback<DB, TB>>(\n    callback: CB,\n  ): UpdateQueryBuilder<DB, UT, TB, ReturningCallbackRow<DB, TB, O, CB>>\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selection: SE,\n  ): UpdateQueryBuilder<DB, UT, TB, ReturningRow<DB, TB, O, SE>>\n\n  returning<SE extends SelectExpression<DB, TB>>(\n    selection: SelectArg<DB, TB, SE>,\n  ): UpdateQueryBuilder<DB, UT, TB, ReturningRow<DB, TB, O, SE>> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectArg(selection),\n      ),\n    })\n  }\n\n  returningAll<T extends TB>(\n    tables: ReadonlyArray<T>,\n  ): UpdateQueryBuilder<DB, UT, TB, ReturningAllRow<DB, T, O>>\n\n  returningAll<T extends TB>(\n    table: T,\n  ): UpdateQueryBuilder<DB, UT, TB, ReturningAllRow<DB, T, O>>\n\n  returningAll(): UpdateQueryBuilder<DB, UT, TB, ReturningAllRow<DB, TB, O>>\n\n  returningAll(table?: any): any {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithReturning(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n\n  output<OE extends OutputExpression<DB, UT>>(\n    selections: readonly OE[],\n  ): UpdateQueryBuilder<\n    DB,\n    UT,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output<CB extends OutputCallback<DB, TB>>(\n    callback: CB,\n  ): UpdateQueryBuilder<\n    DB,\n    UT,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputCallback<CB>>\n  >\n\n  output<OE extends OutputExpression<DB, TB>>(\n    selection: OE,\n  ): UpdateQueryBuilder<\n    DB,\n    UT,\n    TB,\n    ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>\n  >\n\n  output(args: any): any {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectArg(args),\n      ),\n    })\n  }\n\n  outputAll(\n    table: OutputPrefix,\n  ): UpdateQueryBuilder<DB, UT, TB, ReturningAllRow<DB, TB, O>> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithOutput(\n        this.#props.queryNode,\n        parseSelectAll(table),\n      ),\n    })\n  }\n\n  /**\n   * This can be used to add any additional SQL to the end of the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.updateTable('person')\n   *   .set({ age: 39 })\n   *   .where('first_name', '=', 'John')\n   *   .modifyEnd(sql.raw('-- This is a comment'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * update `person`\n   * set `age` = 39\n   * where `first_name` = \"John\" -- This is a comment\n   * ```\n   */\n  modifyEnd(modifier: Expression<any>): UpdateQueryBuilder<DB, UT, TB, O> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithEndModifier(\n        this.#props.queryNode,\n        modifier.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Clears all `returning` clauses from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * db.updateTable('person')\n   *   .returningAll()\n   *   .set({ age: 39 })\n   *   .where('first_name', '=', 'John')\n   *   .clearReturning()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * update \"person\" set \"age\" = 39 where \"first_name\" = \"John\"\n   * ```\n   */\n  clearReturning(): UpdateQueryBuilder<DB, UT, TB, UpdateResult> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithoutReturning(this.#props.queryNode),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   *\n   * If you want to conditionally call a method on `this`, see\n   * the {@link $if} method.\n   *\n   * ### Examples\n   *\n   * The next example uses a helper function `log` to log a query:\n   *\n   * ```ts\n   * import type { Compilable } from 'kysely'\n   * import type { PersonUpdate } from 'type-editor' // imaginary module\n   *\n   * function log<T extends Compilable>(qb: T): T {\n   *   console.log(qb.compile())\n   *   return qb\n   * }\n   *\n   * const values = {\n   *   first_name: 'John',\n   * } satisfies PersonUpdate\n   *\n   * db.updateTable('person')\n   *   .set(values)\n   *   .$call(log)\n   *   .execute()\n   * ```\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  /**\n   * Call `func(this)` if `condition` is true.\n   *\n   * This method is especially handy with optional selects. Any `returning` or `returningAll`\n   * method calls add columns as optional fields to the output type when called inside\n   * the `func` callback. This is because we can't know if those selections were actually\n   * made before running the code.\n   *\n   * You can also call any other methods inside the callback.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { PersonUpdate } from 'type-editor' // imaginary module\n   *\n   * async function updatePerson(id: number, updates: PersonUpdate, returnLastName: boolean) {\n   *   return await db\n   *     .updateTable('person')\n   *     .set(updates)\n   *     .where('id', '=', id)\n   *     .returning(['id', 'first_name'])\n   *     .$if(returnLastName, (qb) => qb.returning('last_name'))\n   *     .executeTakeFirstOrThrow()\n   * }\n   * ```\n   *\n   * Any selections added inside the `if` callback will be added as optional fields to the\n   * output type since we can't know if the selections were actually made before running\n   * the code. In the example above the return type of the `updatePerson` function is:\n   *\n   * ```ts\n   * Promise<{\n   *   id: number\n   *   first_name: string\n   *   last_name?: string\n   * }>\n   * ```\n   */\n  $if<O2>(\n    condition: boolean,\n    func: (qb: this) => UpdateQueryBuilder<any, any, any, O2>,\n  ): O2 extends UpdateResult\n    ? UpdateQueryBuilder<DB, UT, TB, UpdateResult>\n    : O2 extends O & infer E\n      ? UpdateQueryBuilder<DB, UT, TB, O & Partial<E>>\n      : UpdateQueryBuilder<DB, UT, TB, Partial<O2>> {\n    if (condition) {\n      return func(this) as any\n    }\n\n    return new UpdateQueryBuilder({\n      ...this.#props,\n    }) as any\n  }\n\n  /**\n   * Change the output type of the query.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `UpdateQueryBuilder` with a new output type.\n   */\n  $castTo<C>(): UpdateQueryBuilder<DB, UT, TB, C> {\n    return new UpdateQueryBuilder(this.#props)\n  }\n\n  /**\n   * Narrows (parts of) the output type of the query.\n   *\n   * Kysely tries to be as type-safe as possible, but in some cases we have to make\n   * compromises for better maintainability and compilation performance. At present,\n   * Kysely doesn't narrow the output type of the query based on {@link set} input\n   * when using {@link where} and/or {@link returning} or {@link returningAll}.\n   *\n   * This utility method is very useful for these situations, as it removes unncessary\n   * runtime assertion/guard code. Its input type is limited to the output type\n   * of the query, so you can't add a column that doesn't exist, or change a column's\n   * type to something that doesn't exist in its union type.\n   *\n   * ### Examples\n   *\n   * Turn this code:\n   *\n   * ```ts\n   * import type { Person } from 'type-editor' // imaginary module\n   *\n   * const id = 1\n   * const now = new Date().toISOString()\n   *\n   * const person = await db.updateTable('person')\n   *   .set({ deleted_at: now })\n   *   .where('id', '=', id)\n   *   .where('nullable_column', 'is not', null)\n   *   .returningAll()\n   *   .executeTakeFirstOrThrow()\n   *\n   * if (isWithNoNullValue(person)) {\n   *   functionThatExpectsPersonWithNonNullValue(person)\n   * }\n   *\n   * function isWithNoNullValue(person: Person): person is Person & { nullable_column: string } {\n   *   return person.nullable_column != null\n   * }\n   * ```\n   *\n   * Into this:\n   *\n   * ```ts\n   * import type { NotNull } from 'kysely'\n   *\n   * const id = 1\n   * const now = new Date().toISOString()\n   *\n   * const person = await db.updateTable('person')\n   *   .set({ deleted_at: now })\n   *   .where('id', '=', id)\n   *   .where('nullable_column', 'is not', null)\n   *   .returningAll()\n   *   .$narrowType<{ deleted_at: Date; nullable_column: NotNull }>()\n   *   .executeTakeFirstOrThrow()\n   *\n   * functionThatExpectsPersonWithNonNullValue(person)\n   * ```\n   */\n  $narrowType<T>(): UpdateQueryBuilder<DB, UT, TB, NarrowPartial<O, T>> {\n    return new UpdateQueryBuilder(this.#props)\n  }\n\n  /**\n   * Asserts that query's output row type equals the given type `T`.\n   *\n   * This method can be used to simplify excessively complex types to make TypeScript happy\n   * and much faster.\n   *\n   * Kysely uses complex type magic to achieve its type safety. This complexity is sometimes too much\n   * for TypeScript and you get errors like this:\n   *\n   * ```\n   * error TS2589: Type instantiation is excessively deep and possibly infinite.\n   * ```\n   *\n   * In these case you can often use this method to help TypeScript a little bit. When you use this\n   * method to assert the output type of a query, Kysely can drop the complex output type that\n   * consists of multiple nested helper types and replace it with the simple asserted type.\n   *\n   * Using this method doesn't reduce type safety at all. You have to pass in a type that is\n   * structurally equal to the current type.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { PersonUpdate, PetUpdate, Species } from 'type-editor' // imaginary module\n   *\n   * const person = {\n   *   id: 1,\n   *   gender: 'other',\n   * } satisfies PersonUpdate\n   *\n   * const pet = {\n   *   name: 'Fluffy',\n   * } satisfies PetUpdate\n   *\n   * const result = await db\n   *   .with('updated_person', (qb) => qb\n   *     .updateTable('person')\n   *     .set(person)\n   *     .where('id', '=', person.id)\n   *     .returning('first_name')\n   *     .$assertType<{ first_name: string }>()\n   *   )\n   *   .with('updated_pet', (qb) => qb\n   *     .updateTable('pet')\n   *     .set(pet)\n   *     .where('owner_id', '=', person.id)\n   *     .returning(['name as pet_name', 'species'])\n   *     .$assertType<{ pet_name: string, species: Species }>()\n   *   )\n   *   .selectFrom(['updated_person', 'updated_pet'])\n   *   .selectAll()\n   *   .executeTakeFirstOrThrow()\n   * ```\n   */\n  $assertType<T extends O>(): O extends T\n    ? UpdateQueryBuilder<DB, UT, TB, T>\n    : KyselyTypeError<`$assertType() call failed: The type passed in is not equal to the output type of the query.`> {\n    return new UpdateQueryBuilder(this.#props) as unknown as any\n  }\n\n  /**\n   * Returns a copy of this UpdateQueryBuilder instance with the given plugin installed.\n   */\n  withPlugin(plugin: KyselyPlugin): UpdateQueryBuilder<DB, UT, TB, O> {\n    return new UpdateQueryBuilder({\n      ...this.#props,\n      executor: this.#props.executor.withPlugin(plugin),\n    })\n  }\n\n  toOperationNode(): UpdateQueryNode {\n    return this.#props.executor.transformQuery(\n      this.#props.queryNode,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery<SimplifyResult<O>> {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  /**\n   * Executes the query and returns an array of rows.\n   *\n   * Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.\n   */\n  async execute(): Promise<SimplifyResult<O>[]> {\n    const compiledQuery = this.compile()\n\n    const result = await this.#props.executor.executeQuery<O>(compiledQuery)\n\n    const { adapter } = this.#props.executor\n    const query = compiledQuery.query as UpdateQueryNode\n\n    if (\n      (query.returning && adapter.supportsReturning) ||\n      (query.output && adapter.supportsOutput)\n    ) {\n      return result.rows as any\n    }\n\n    return [\n      new UpdateResult(\n        result.numAffectedRows ?? BigInt(0),\n        result.numChangedRows,\n      ) as any,\n    ]\n  }\n\n  /**\n   * Executes the query and returns the first result or undefined if\n   * the query returned no result.\n   */\n  async executeTakeFirst(): Promise<SimplifySingleResult<O>> {\n    const [result] = await this.execute()\n    return result as SimplifySingleResult<O>\n  }\n\n  /**\n   * Executes the query and returns the first result or throws if\n   * the query returned no result.\n   *\n   * By default an instance of {@link NoResultError} is thrown, but you can\n   * provide a custom error class, or callback as the only argument to throw a different\n   * error.\n   */\n  async executeTakeFirstOrThrow(\n    errorConstructor:\n      | NoResultErrorConstructor\n      | ((node: QueryNode) => Error) = NoResultError,\n  ): Promise<SimplifyResult<O>> {\n    const result = await this.executeTakeFirst()\n\n    if (result === undefined) {\n      const error = isNoResultErrorConstructor(errorConstructor)\n        ? new errorConstructor(this.toOperationNode())\n        : errorConstructor(this.toOperationNode())\n\n      throw error\n    }\n\n    return result as SimplifyResult<O>\n  }\n\n  async *stream(chunkSize: number = 100): AsyncIterableIterator<O> {\n    const compiledQuery = this.compile()\n\n    const stream = this.#props.executor.stream<O>(compiledQuery, chunkSize)\n\n    for await (const item of stream) {\n      yield* item.rows\n    }\n  }\n\n  async explain<ER extends Record<string, any> = Record<string, any>>(\n    format?: ExplainFormat,\n    options?: Expression<any>,\n  ): Promise<ER[]> {\n    const builder = new UpdateQueryBuilder<DB, UT, TB, ER>({\n      ...this.#props,\n      queryNode: QueryNode.cloneWithExplain(\n        this.#props.queryNode,\n        format,\n        options,\n      ),\n    })\n\n    return await builder.execute()\n  }\n}\n\nexport interface UpdateQueryBuilderProps {\n  readonly queryId: QueryId\n  readonly queryNode: UpdateQueryNode\n  readonly executor: QueryExecutor\n}\n\nexport type UpdateQueryBuilderWithInnerJoin<\n  DB,\n  UT extends keyof DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? InnerJoinedBuilder<DB, UT, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? UpdateQueryBuilder<DB, UT, TB | TE, O>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? InnerJoinedBuilder<DB, UT, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? InnerJoinedBuilder<DB, UT, TB, O, QA, QO>\n        : never\n\ntype InnerJoinedBuilder<\n  DB,\n  UT extends keyof DB,\n  TB extends keyof DB,\n  O,\n  A extends string,\n  R,\n> = A extends keyof DB\n  ? UpdateQueryBuilder<InnerJoinedDB<DB, A, R>, UT, TB | A, O>\n  : // Much faster non-recursive solution for the simple case.\n    UpdateQueryBuilder<DB & ShallowRecord<A, R>, UT, TB | A, O>\n\ntype InnerJoinedDB<DB, A extends string, R> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A ? R : C extends keyof DB ? DB[C] : never\n}>\n\nexport type UpdateQueryBuilderWithLeftJoin<\n  DB,\n  UT extends keyof DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? LeftJoinedBuilder<DB, UT, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? LeftJoinedBuilder<DB, UT, TB, O, TE, DB[TE]>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? LeftJoinedBuilder<DB, UT, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? LeftJoinedBuilder<DB, UT, TB, O, QA, QO>\n        : never\n\ntype LeftJoinedBuilder<\n  DB,\n  UT extends keyof DB,\n  TB extends keyof DB,\n  O,\n  A extends keyof any,\n  R,\n> = A extends keyof DB\n  ? UpdateQueryBuilder<LeftJoinedDB<DB, A, R>, UT, TB | A, O>\n  : // Much faster non-recursive solution for the simple case.\n    UpdateQueryBuilder<DB & ShallowRecord<A, Nullable<R>>, UT, TB | A, O>\n\ntype LeftJoinedDB<DB, A extends keyof any, R> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A\n    ? Nullable<R>\n    : C extends keyof DB\n      ? DB[C]\n      : never\n}>\n\nexport type UpdateQueryBuilderWithRightJoin<\n  DB,\n  UT extends keyof DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? RightJoinedBuilder<DB, UT, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? RightJoinedBuilder<DB, UT, TB, O, TE, DB[TE]>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? RightJoinedBuilder<DB, UT, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? RightJoinedBuilder<DB, UT, TB, O, QA, QO>\n        : never\n\ntype RightJoinedBuilder<\n  DB,\n  UT extends keyof DB,\n  TB extends keyof DB,\n  O,\n  A extends keyof any,\n  R,\n> = UpdateQueryBuilder<RightJoinedDB<DB, TB, A, R>, UT, TB | A, O>\n\ntype RightJoinedDB<\n  DB,\n  TB extends keyof DB,\n  A extends keyof any,\n  R,\n> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A\n    ? R\n    : C extends TB\n      ? Nullable<DB[C]>\n      : C extends keyof DB\n        ? DB[C]\n        : never\n}>\n\nexport type UpdateQueryBuilderWithFullJoin<\n  DB,\n  UT extends keyof DB,\n  TB extends keyof DB,\n  O,\n  TE extends TableExpression<DB, TB>,\n> = TE extends `${infer T} as ${infer A}`\n  ? T extends keyof DB\n    ? OuterJoinedBuilder<DB, UT, TB, O, A, DB[T]>\n    : never\n  : TE extends keyof DB\n    ? OuterJoinedBuilder<DB, UT, TB, O, TE, DB[TE]>\n    : TE extends AliasedExpression<infer QO, infer QA>\n      ? OuterJoinedBuilder<DB, UT, TB, O, QA, QO>\n      : TE extends (qb: any) => AliasedExpression<infer QO, infer QA>\n        ? OuterJoinedBuilder<DB, UT, TB, O, QA, QO>\n        : never\n\ntype OuterJoinedBuilder<\n  DB,\n  UT extends keyof DB,\n  TB extends keyof DB,\n  O,\n  A extends keyof any,\n  R,\n> = UpdateQueryBuilder<OuterJoinedBuilderDB<DB, TB, A, R>, UT, TB | A, O>\n\ntype OuterJoinedBuilderDB<\n  DB,\n  TB extends keyof DB,\n  A extends keyof any,\n  R,\n> = DrainOuterGeneric<{\n  [C in keyof DB | A]: C extends A\n    ? Nullable<R>\n    : C extends TB\n      ? Nullable<DB[C]>\n      : C extends keyof DB\n        ? DB[C]\n        : never\n}>\n"
  },
  {
    "path": "src/query-builder/update-result.ts",
    "content": "export class UpdateResult {\n  /**\n   * The number of rows the update query updated (even if not changed).\n   */\n  readonly numUpdatedRows: bigint\n\n  /**\n   * The number of rows the update query changed.\n   *\n   * This is **optional** and only supported in dialects such as MySQL.\n   * You would probably use {@link numUpdatedRows} in most cases.\n   */\n  readonly numChangedRows?: bigint\n\n  constructor(numUpdatedRows: bigint, numChangedRows: bigint | undefined) {\n    this.numUpdatedRows = numUpdatedRows\n    this.numChangedRows = numChangedRows\n  }\n}\n"
  },
  {
    "path": "src/query-builder/where-interface.ts",
    "content": "import type {\n  ComparisonOperatorExpression,\n  OperandValueExpressionOrList,\n} from '../parser/binary-operation-parser.js'\nimport type { ReferenceExpression } from '../parser/reference-parser.js'\nimport type { SqlBool } from '../util/type-utils.js'\nimport type { ExpressionBuilder } from '../expression/expression-builder.js'\nimport type { ExpressionOrFactory } from '../parser/expression-parser.js'\n\nexport interface WhereInterface<DB, TB extends keyof DB> {\n  /**\n   * Adds a `where` expression to the query.\n   *\n   * Calling this method multiple times will combine the expressions using `and`.\n   *\n   * Also see {@link whereRef}\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"where\", \"Simple where clause\", 10) -->\n   *\n   * `where` method calls are combined with `AND`:\n   *\n   * ```ts\n   * const person = await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .where('first_name', '=', 'Jennifer')\n   *   .where('age', '>', 40)\n   *   .executeTakeFirst()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\" where \"first_name\" = $1 and \"age\" > $2\n   * ```\n   *\n   * Operator can be any supported operator or if the typings don't support it\n   * you can always use:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * sql`your operator`\n   * ```\n   *\n   * <!-- siteExample(\"where\", \"Where in\", 20) -->\n   *\n   * Find multiple items using a list of identifiers:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .where('id', 'in', [1, 2, 3])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\" where \"id\" in ($1, $2, $3)\n   * ```\n   *\n   * <!-- siteExample(\"where\", \"Object filter\", 30) -->\n   *\n   * You can use the `and` function to create a simple equality\n   * filter using an object\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .where((eb) => eb.and({\n   *     first_name: 'Jennifer',\n   *     last_name: eb.ref('first_name')\n   *   }))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where (\n   *   \"first_name\" = $1\n   *   and \"last_name\" = \"first_name\"\n   * )\n   * ```\n   *\n   * <!-- siteExample(\"where\", \"OR where\", 40) -->\n   *\n   * To combine conditions using `OR`, you can use the expression builder.\n   * There are two ways to create `OR` expressions. Both are shown in this\n   * example:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   // 1. Using the `or` method on the expression builder:\n   *   .where((eb) => eb.or([\n   *     eb('first_name', '=', 'Jennifer'),\n   *     eb('first_name', '=', 'Sylvester')\n   *   ]))\n   *   // 2. Chaining expressions using the `or` method on the\n   *   // created expressions:\n   *   .where((eb) =>\n   *     eb('last_name', '=', 'Aniston').or('last_name', '=', 'Stallone')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where (\n   *   (\"first_name\" = $1 or \"first_name\" = $2)\n   *   and\n   *   (\"last_name\" = $3 or \"last_name\" = $4)\n   * )\n   * ```\n   *\n   * <!-- siteExample(\"where\", \"Conditional where calls\", 50) -->\n   *\n   * You can add expressions conditionally like this:\n   *\n   * ```ts\n   * import { Expression, SqlBool } from 'kysely'\n   *\n   * const firstName: string | undefined = 'Jennifer'\n   * const lastName: string | undefined = 'Aniston'\n   * const under18 = true\n   * const over60 = true\n   *\n   * let query = db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *\n   * if (firstName) {\n   *   // The query builder is immutable. Remember to reassign\n   *   // the result back to the query variable.\n   *   query = query.where('first_name', '=', firstName)\n   * }\n   *\n   * if (lastName) {\n   *   query = query.where('last_name', '=', lastName)\n   * }\n   *\n   * if (under18 || over60) {\n   *   // Conditional OR expressions can be added like this.\n   *   query = query.where((eb) => {\n   *     const ors: Expression<SqlBool>[] = []\n   *\n   *     if (under18) {\n   *       ors.push(eb('age', '<', 18))\n   *     }\n   *\n   *     if (over60) {\n   *       ors.push(eb('age', '>', 60))\n   *     }\n   *\n   *     return eb.or(ors)\n   *   })\n   * }\n   *\n   * const persons = await query.execute()\n   * ```\n   *\n   * Both the first and third argument can also be arbitrary expressions like\n   * subqueries. An expression can defined by passing a function and calling\n   * the methods of the {@link ExpressionBuilder} passed to the callback:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .where(\n   *     (qb) => qb.selectFrom('pet')\n   *       .select('pet.name')\n   *       .whereRef('pet.owner_id', '=', 'person.id')\n   *       .limit(1),\n   *     '=',\n   *     'Fluffy'\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select *\n   * from \"person\"\n   * where (\n   *   select \"pet\".\"name\"\n   *   from \"pet\"\n   *   where \"pet\".\"owner_id\" = \"person\".\"id\"\n   *   limit $1\n   * ) = $2\n   * ```\n   *\n   * A `where in` query can be built by using the `in` operator and an array\n   * of values. The values in the array can also be expressions:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .where('person.id', 'in', [100, 200, 300])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\" where \"id\" in ($1, $2, $3)\n   * ```\n   *\n   * <!-- siteExample(\"where\", \"Complex where clause\", 60) -->\n   *\n   * For complex `where` expressions you can pass in a single callback and\n   * use the `ExpressionBuilder` to build your expression:\n   *\n   * ```ts\n   * const firstName = 'Jennifer'\n   * const maxAge = 60\n   *\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll('person')\n   *   .where(({ eb, or, and, not, exists, selectFrom }) => and([\n   *     or([\n   *       eb('first_name', '=', firstName),\n   *       eb('age', '<', maxAge)\n   *     ]),\n   *     not(exists(\n   *       selectFrom('pet')\n   *         .select('pet.id')\n   *         .whereRef('pet.owner_id', '=', 'person.id')\n   *     ))\n   *   ]))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*\n   * from \"person\"\n   * where (\n   *   (\n   *     \"first_name\" = $1\n   *     or \"age\" < $2\n   *   )\n   *   and not exists (\n   *     select \"pet\".\"id\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\"\n   *   )\n   * )\n   * ```\n   *\n   * If everything else fails, you can always use the {@link sql} tag\n   * as any of the arguments, including the operator:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .where(\n   *     sql<string>`coalesce(first_name, last_name)`,\n   *     'like',\n   *     '%' + name + '%',\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\"\n   * where coalesce(first_name, last_name) like $1\n   * ```\n   *\n   * In all examples above the columns were known at compile time\n   * (except for the raw {@link sql} expressions). By default kysely only\n   * allows you to refer to columns that exist in the database **and**\n   * can be referred to in the current query and context.\n   *\n   * Sometimes you may want to refer to columns that come from the user\n   * input and thus are not available at compile time.\n   *\n   * You have two options, the {@link sql} tag or `db.dynamic`. The example below\n   * uses both:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   * const { ref } = db.dynamic\n   *\n   * const columnFromUserInput: string = 'id'\n   *\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll()\n   *   .where(ref(columnFromUserInput), '=', 1)\n   *   .where(sql.id(columnFromUserInput), '=', 2)\n   *   .execute()\n   * ```\n   */\n  where<\n    RE extends ReferenceExpression<DB, TB>,\n    VE extends OperandValueExpressionOrList<DB, TB, RE>,\n  >(\n    lhs: RE,\n    op: ComparisonOperatorExpression,\n    rhs: VE,\n  ): WhereInterface<DB, TB>\n\n  where<E extends ExpressionOrFactory<DB, TB, SqlBool>>(\n    expression: E,\n  ): WhereInterface<DB, TB>\n\n  /**\n   * Adds a `where` clause where both sides of the operator are references\n   * to columns.\n   *\n   * The normal `where` method treats the right hand side argument as a\n   * value by default. `whereRef` treats it as a column reference. This method is\n   * expecially useful with joins and correlated subqueries.\n   *\n   * ### Examples\n   *\n   * Usage with a join:\n   *\n   * ```ts\n   * db.selectFrom(['person', 'pet'])\n   *   .selectAll()\n   *   .whereRef('person.first_name', '=', 'pet.name')\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\", \"pet\" where \"person\".\"first_name\" = \"pet\".\"name\"\n   * ```\n   *\n   * Usage in a subquery:\n   *\n   * ```ts\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .selectAll('person')\n   *   .select((eb) => eb\n   *     .selectFrom('pet')\n   *     .select('name')\n   *     .whereRef('pet.owner_id', '=', 'person.id')\n   *     .limit(1)\n   *     .as('pet_name')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".*, (\n   *   select \"name\"\n   *   from \"pet\"\n   *   where \"pet\".\"owner_id\" = \"person\".\"id\"\n   *   limit $1\n   * ) as \"pet_name\"\n   * from \"person\"\n   */\n  whereRef<\n    LRE extends ReferenceExpression<DB, TB>,\n    RRE extends ReferenceExpression<DB, TB>,\n  >(\n    lhs: LRE,\n    op: ComparisonOperatorExpression,\n    rhs: RRE,\n  ): WhereInterface<DB, TB>\n\n  /**\n   * Clears all where expressions from the query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * db.selectFrom('person')\n   *   .selectAll()\n   *   .where('id','=',42)\n   *   .clearWhere()\n   * ```\n   *\n   * The generated SQL(PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\"\n   * ```\n   */\n  clearWhere(): WhereInterface<DB, TB>\n}\n"
  },
  {
    "path": "src/query-compiler/compiled-query.ts",
    "content": "import { RawNode } from '../operation-node/raw-node.js'\nimport { freeze } from '../util/object-utils.js'\nimport { createQueryId, type QueryId } from '../util/query-id.js'\nimport type { RootOperationNode } from './query-compiler.js'\n\nexport interface CompiledQuery<O = unknown> {\n  readonly query: RootOperationNode\n  readonly queryId: QueryId\n  readonly sql: string\n  readonly parameters: ReadonlyArray<unknown>\n}\n\ntype CompiledQueryFactory = Readonly<{\n  raw(sql: string, parameters?: unknown[]): Readonly<CompiledQuery>\n}>\n\nexport const CompiledQuery: CompiledQueryFactory = freeze<CompiledQueryFactory>(\n  {\n    raw(sql, parameters = []) {\n      return freeze({\n        sql,\n        query: RawNode.createWithSql(sql),\n        parameters: freeze(parameters),\n        queryId: createQueryId(),\n      })\n    },\n  },\n)\n"
  },
  {
    "path": "src/query-compiler/default-query-compiler.ts",
    "content": "import type { AliasNode } from '../operation-node/alias-node.js'\nimport type { AndNode } from '../operation-node/and-node.js'\nimport type { CheckConstraintNode } from '../operation-node/check-constraint-node.js'\nimport type { AddColumnNode } from '../operation-node/add-column-node.js'\nimport type { ColumnUpdateNode } from '../operation-node/column-update-node.js'\nimport type { CreateIndexNode } from '../operation-node/create-index-node.js'\nimport { CreateTableNode } from '../operation-node/create-table-node.js'\nimport type { DataTypeNode } from '../operation-node/data-type-node.js'\nimport type { DeleteQueryNode } from '../operation-node/delete-query-node.js'\nimport type { DropIndexNode } from '../operation-node/drop-index-node.js'\nimport type { DropTableNode } from '../operation-node/drop-table-node.js'\nimport type { FromNode } from '../operation-node/from-node.js'\nimport type { GroupByItemNode } from '../operation-node/group-by-item-node.js'\nimport type { GroupByNode } from '../operation-node/group-by-node.js'\nimport type { IdentifierNode } from '../operation-node/identifier-node.js'\nimport { InsertQueryNode } from '../operation-node/insert-query-node.js'\nimport type { JoinNode, JoinType } from '../operation-node/join-node.js'\nimport type { LimitNode } from '../operation-node/limit-node.js'\nimport type { ListNode } from '../operation-node/list-node.js'\nimport type { OffsetNode } from '../operation-node/offset-node.js'\nimport type { OnConflictNode } from '../operation-node/on-conflict-node.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport { OperationNodeVisitor } from '../operation-node/operation-node-visitor.js'\nimport { OperatorNode } from '../operation-node/operator-node.js'\nimport type { OrNode } from '../operation-node/or-node.js'\nimport type { OrderByItemNode } from '../operation-node/order-by-item-node.js'\nimport type { OrderByNode } from '../operation-node/order-by-node.js'\nimport { ParensNode } from '../operation-node/parens-node.js'\nimport type { PrimitiveValueListNode } from '../operation-node/primitive-value-list-node.js'\nimport type { QueryNode } from '../operation-node/query-node.js'\nimport { RawNode } from '../operation-node/raw-node.js'\nimport type { ReferenceNode } from '../operation-node/reference-node.js'\nimport type { ReferencesNode } from '../operation-node/references-node.js'\nimport type { ReturningNode } from '../operation-node/returning-node.js'\nimport type { SelectAllNode } from '../operation-node/select-all-node.js'\nimport type { SelectQueryNode } from '../operation-node/select-query-node.js'\nimport type { SelectionNode } from '../operation-node/selection-node.js'\nimport type { TableNode } from '../operation-node/table-node.js'\nimport type { PrimaryKeyConstraintNode } from '../operation-node/primary-key-constraint-node.js'\nimport type { UniqueConstraintNode } from '../operation-node/unique-constraint-node.js'\nimport type { UpdateQueryNode } from '../operation-node/update-query-node.js'\nimport type { ValueListNode } from '../operation-node/value-list-node.js'\nimport type { ValueNode } from '../operation-node/value-node.js'\nimport type { WhereNode } from '../operation-node/where-node.js'\nimport type { CommonTableExpressionNode } from '../operation-node/common-table-expression-node.js'\nimport type { WithNode } from '../operation-node/with-node.js'\nimport {\n  freeze,\n  isString,\n  isNumber,\n  isBoolean,\n  isNull,\n  isDate,\n  isBigInt,\n} from '../util/object-utils.js'\nimport type { CompiledQuery } from './compiled-query.js'\nimport type { RootOperationNode, QueryCompiler } from './query-compiler.js'\nimport type { HavingNode } from '../operation-node/having-node.js'\nimport type { CreateSchemaNode } from '../operation-node/create-schema-node.js'\nimport type { DropSchemaNode } from '../operation-node/drop-schema-node.js'\nimport type {\n  AlterTableColumnAlterationNode,\n  AlterTableNode,\n} from '../operation-node/alter-table-node.js'\nimport type { DropColumnNode } from '../operation-node/drop-column-node.js'\nimport type { RenameColumnNode } from '../operation-node/rename-column-node.js'\nimport type { AlterColumnNode } from '../operation-node/alter-column-node.js'\nimport type { AddConstraintNode } from '../operation-node/add-constraint-node.js'\nimport type { DropConstraintNode } from '../operation-node/drop-constraint-node.js'\nimport type { ForeignKeyConstraintNode } from '../operation-node/foreign-key-constraint-node.js'\nimport type { ColumnDefinitionNode } from '../operation-node/column-definition-node.js'\nimport type { ModifyColumnNode } from '../operation-node/modify-column-node.js'\nimport type { OnDuplicateKeyNode } from '../operation-node/on-duplicate-key-node.js'\nimport type { ColumnNode } from '../operation-node/column-node.js'\nimport { CreateViewNode } from '../operation-node/create-view-node.js'\nimport type { DropViewNode } from '../operation-node/drop-view-node.js'\nimport type { GeneratedNode } from '../operation-node/generated-node.js'\nimport type { DefaultValueNode } from '../operation-node/default-value-node.js'\nimport type { OnNode } from '../operation-node/on-node.js'\nimport type { ValuesNode } from '../operation-node/values-node.js'\nimport type { CommonTableExpressionNameNode } from '../operation-node/common-table-expression-name-node.js'\nimport type {\n  SelectModifier,\n  SelectModifierNode,\n} from '../operation-node/select-modifier-node.js'\nimport type { CreateTypeNode } from '../operation-node/create-type-node.js'\nimport type { DropTypeNode } from '../operation-node/drop-type-node.js'\nimport type { ExplainNode } from '../operation-node/explain-node.js'\nimport type { SchemableIdentifierNode } from '../operation-node/schemable-identifier-node.js'\nimport type { DefaultInsertValueNode } from '../operation-node/default-insert-value-node.js'\nimport type { AggregateFunctionNode } from '../operation-node/aggregate-function-node.js'\nimport type { OverNode } from '../operation-node/over-node.js'\nimport type { PartitionByNode } from '../operation-node/partition-by-node.js'\nimport type { PartitionByItemNode } from '../operation-node/partition-by-item-node.js'\nimport { SetOperationNode } from '../operation-node/set-operation-node.js'\nimport type { BinaryOperationNode } from '../operation-node/binary-operation-node.js'\nimport type { UnaryOperationNode } from '../operation-node/unary-operation-node.js'\nimport type { UsingNode } from '../operation-node/using-node.js'\nimport type { FunctionNode } from '../operation-node/function-node.js'\nimport type { CaseNode } from '../operation-node/case-node.js'\nimport { WhenNode } from '../operation-node/when-node.js'\nimport type { JSONReferenceNode } from '../operation-node/json-reference-node.js'\nimport type { JSONPathNode } from '../operation-node/json-path-node.js'\nimport type { JSONPathLegNode } from '../operation-node/json-path-leg-node.js'\nimport type { JSONOperatorChainNode } from '../operation-node/json-operator-chain-node.js'\nimport type { TupleNode } from '../operation-node/tuple-node.js'\nimport type { MergeQueryNode } from '../operation-node/merge-query-node.js'\nimport type { MatchedNode } from '../operation-node/matched-node.js'\nimport type { AddIndexNode } from '../operation-node/add-index-node.js'\nimport type { CastNode } from '../operation-node/cast-node.js'\nimport type { FetchNode } from '../operation-node/fetch-node.js'\nimport type { TopNode } from '../operation-node/top-node.js'\nimport type { OutputNode } from '../operation-node/output-node.js'\nimport type { RefreshMaterializedViewNode } from '../operation-node/refresh-materialized-view-node.js'\nimport type { OrActionNode } from '../operation-node/or-action-node.js'\nimport { logOnce } from '../util/log-once.js'\nimport type { CollateNode } from '../operation-node/collate-node.js'\nimport type { QueryId } from '../util/query-id.js'\nimport type { RenameConstraintNode } from '../operation-node/rename-constraint-node.js'\n\nconst LIT_WRAP_REGEX = /'/g\n\nexport class DefaultQueryCompiler\n  extends OperationNodeVisitor\n  implements QueryCompiler\n{\n  #sql = ''\n  #parameters: unknown[] = []\n\n  protected get numParameters(): number {\n    return this.#parameters.length\n  }\n\n  compileQuery(node: RootOperationNode, queryId: QueryId): CompiledQuery {\n    this.#sql = ''\n    this.#parameters = []\n    this.nodeStack.splice(0, this.nodeStack.length)\n\n    this.visitNode(node)\n\n    return freeze({\n      query: node,\n      queryId,\n      sql: this.getSql(),\n      parameters: [...this.#parameters],\n    })\n  }\n\n  protected getSql(): string {\n    return this.#sql\n  }\n\n  protected override visitSelectQuery(node: SelectQueryNode): void {\n    const wrapInParens =\n      this.parentNode !== undefined &&\n      !ParensNode.is(this.parentNode) &&\n      !InsertQueryNode.is(this.parentNode) &&\n      !CreateTableNode.is(this.parentNode) &&\n      !CreateViewNode.is(this.parentNode) &&\n      !SetOperationNode.is(this.parentNode)\n\n    if (this.parentNode === undefined && node.explain) {\n      this.visitNode(node.explain)\n      this.append(' ')\n    }\n\n    if (wrapInParens) {\n      this.append('(')\n    }\n\n    if (node.with) {\n      this.visitNode(node.with)\n      this.append(' ')\n    }\n\n    this.append('select')\n\n    if (node.distinctOn) {\n      this.append(' ')\n      this.compileDistinctOn(node.distinctOn)\n    }\n\n    if (node.frontModifiers?.length) {\n      this.append(' ')\n      this.compileList(node.frontModifiers, ' ')\n    }\n\n    if (node.top) {\n      this.append(' ')\n      this.visitNode(node.top)\n    }\n\n    if (node.selections) {\n      this.append(' ')\n      this.compileList(node.selections)\n    }\n\n    if (node.from) {\n      this.append(' ')\n      this.visitNode(node.from)\n    }\n\n    if (node.joins) {\n      this.append(' ')\n      this.compileList(node.joins, ' ')\n    }\n\n    if (node.where) {\n      this.append(' ')\n      this.visitNode(node.where)\n    }\n\n    if (node.groupBy) {\n      this.append(' ')\n      this.visitNode(node.groupBy)\n    }\n\n    if (node.having) {\n      this.append(' ')\n      this.visitNode(node.having)\n    }\n\n    if (node.setOperations) {\n      this.append(' ')\n      this.compileList(node.setOperations, ' ')\n    }\n\n    if (node.orderBy) {\n      this.append(' ')\n      this.visitNode(node.orderBy)\n    }\n\n    if (node.limit) {\n      this.append(' ')\n      this.visitNode(node.limit)\n    }\n\n    if (node.offset) {\n      this.append(' ')\n      this.visitNode(node.offset)\n    }\n\n    if (node.fetch) {\n      this.append(' ')\n      this.visitNode(node.fetch)\n    }\n\n    if (node.endModifiers?.length) {\n      this.append(' ')\n      this.compileList(this.sortSelectModifiers([...node.endModifiers]), ' ')\n    }\n\n    if (wrapInParens) {\n      this.append(')')\n    }\n  }\n\n  protected override visitFrom(node: FromNode): void {\n    this.append('from ')\n    this.compileList(node.froms)\n  }\n\n  protected override visitSelection(node: SelectionNode): void {\n    this.visitNode(node.selection)\n  }\n\n  protected override visitColumn(node: ColumnNode): void {\n    this.visitNode(node.column)\n  }\n\n  protected compileDistinctOn(expressions: ReadonlyArray<OperationNode>): void {\n    this.append('distinct on (')\n    this.compileList(expressions)\n    this.append(')')\n  }\n\n  protected compileList(\n    nodes: ReadonlyArray<OperationNode>,\n    separator = ', ',\n  ): void {\n    const lastIndex = nodes.length - 1\n\n    for (let i = 0; i <= lastIndex; i++) {\n      this.visitNode(nodes[i])\n\n      if (i < lastIndex) {\n        this.append(separator)\n      }\n    }\n  }\n\n  protected override visitWhere(node: WhereNode): void {\n    this.append('where ')\n    this.visitNode(node.where)\n  }\n\n  protected override visitHaving(node: HavingNode): void {\n    this.append('having ')\n    this.visitNode(node.having)\n  }\n\n  protected override visitInsertQuery(node: InsertQueryNode): void {\n    const wrapInParens =\n      this.parentNode !== undefined &&\n      !ParensNode.is(this.parentNode) &&\n      !RawNode.is(this.parentNode) &&\n      !WhenNode.is(this.parentNode)\n\n    if (this.parentNode === undefined && node.explain) {\n      this.visitNode(node.explain)\n      this.append(' ')\n    }\n\n    if (wrapInParens) {\n      this.append('(')\n    }\n\n    if (node.with) {\n      this.visitNode(node.with)\n      this.append(' ')\n    }\n\n    this.append(node.replace ? 'replace' : 'insert')\n\n    // TODO: remove in 0.29.\n    if (node.ignore) {\n      logOnce(\n        '`InsertQueryNode.ignore` is deprecated. Use `InsertQueryNode.orAction` instead.',\n      )\n      this.append(' ignore')\n    }\n\n    if (node.orAction) {\n      this.append(' ')\n      this.visitNode(node.orAction)\n    }\n\n    if (node.top) {\n      this.append(' ')\n      this.visitNode(node.top)\n    }\n\n    if (node.into) {\n      this.append(' into ')\n      this.visitNode(node.into)\n    }\n\n    if (node.columns) {\n      this.append(' (')\n      this.compileList(node.columns)\n      this.append(')')\n    }\n\n    if (node.output) {\n      this.append(' ')\n      this.visitNode(node.output)\n    }\n\n    if (node.values) {\n      this.append(' ')\n      this.visitNode(node.values)\n    }\n\n    if (node.defaultValues) {\n      this.append(' ')\n      this.append('default values')\n    }\n\n    if (node.onConflict) {\n      this.append(' ')\n      this.visitNode(node.onConflict)\n    }\n\n    if (node.onDuplicateKey) {\n      this.append(' ')\n      this.visitNode(node.onDuplicateKey)\n    }\n\n    if (node.returning) {\n      this.append(' ')\n      this.visitNode(node.returning)\n    }\n\n    if (wrapInParens) {\n      this.append(')')\n    }\n\n    if (node.endModifiers?.length) {\n      this.append(' ')\n      this.compileList(node.endModifiers, ' ')\n    }\n  }\n\n  protected override visitValues(node: ValuesNode): void {\n    this.append('values ')\n    this.compileList(node.values)\n  }\n\n  protected override visitDeleteQuery(node: DeleteQueryNode): void {\n    const wrapInParens =\n      this.parentNode !== undefined &&\n      !ParensNode.is(this.parentNode) &&\n      !RawNode.is(this.parentNode)\n\n    if (this.parentNode === undefined && node.explain) {\n      this.visitNode(node.explain)\n      this.append(' ')\n    }\n\n    if (wrapInParens) {\n      this.append('(')\n    }\n\n    if (node.with) {\n      this.visitNode(node.with)\n      this.append(' ')\n    }\n\n    this.append('delete ')\n\n    if (node.top) {\n      this.visitNode(node.top)\n      this.append(' ')\n    }\n\n    this.visitNode(node.from)\n\n    if (node.output) {\n      this.append(' ')\n      this.visitNode(node.output)\n    }\n\n    if (node.using) {\n      this.append(' ')\n      this.visitNode(node.using)\n    }\n\n    if (node.joins) {\n      this.append(' ')\n      this.compileList(node.joins, ' ')\n    }\n\n    if (node.where) {\n      this.append(' ')\n      this.visitNode(node.where)\n    }\n\n    if (node.orderBy) {\n      this.append(' ')\n      this.visitNode(node.orderBy)\n    }\n\n    if (node.limit) {\n      this.append(' ')\n      this.visitNode(node.limit)\n    }\n\n    if (node.returning) {\n      this.append(' ')\n      this.visitNode(node.returning)\n    }\n\n    if (wrapInParens) {\n      this.append(')')\n    }\n\n    if (node.endModifiers?.length) {\n      this.append(' ')\n      this.compileList(node.endModifiers, ' ')\n    }\n  }\n\n  protected override visitReturning(node: ReturningNode): void {\n    this.append('returning ')\n    this.compileList(node.selections)\n  }\n\n  protected override visitAlias(node: AliasNode): void {\n    this.visitNode(node.node)\n    this.append(' as ')\n    this.visitNode(node.alias)\n  }\n\n  protected override visitReference(node: ReferenceNode): void {\n    if (node.table) {\n      this.visitNode(node.table)\n      this.append('.')\n    }\n\n    this.visitNode(node.column)\n  }\n\n  protected override visitSelectAll(_: SelectAllNode): void {\n    this.append('*')\n  }\n\n  protected override visitIdentifier(node: IdentifierNode): void {\n    this.append(this.getLeftIdentifierWrapper())\n    this.compileUnwrappedIdentifier(node)\n    this.append(this.getRightIdentifierWrapper())\n  }\n\n  protected compileUnwrappedIdentifier(node: IdentifierNode): void {\n    if (!isString(node.name)) {\n      throw new Error(\n        'a non-string identifier was passed to compileUnwrappedIdentifier.',\n      )\n    }\n\n    this.append(this.sanitizeIdentifier(node.name))\n  }\n\n  protected override visitAnd(node: AndNode): void {\n    this.visitNode(node.left)\n    this.append(' and ')\n    this.visitNode(node.right)\n  }\n\n  protected override visitOr(node: OrNode): void {\n    this.visitNode(node.left)\n    this.append(' or ')\n    this.visitNode(node.right)\n  }\n\n  protected override visitValue(node: ValueNode): void {\n    if (node.immediate) {\n      this.appendImmediateValue(node.value)\n    } else {\n      this.appendValue(node.value)\n    }\n  }\n\n  protected override visitValueList(node: ValueListNode): void {\n    this.append('(')\n    this.compileList(node.values)\n    this.append(')')\n  }\n\n  protected override visitTuple(node: TupleNode): void {\n    this.append('(')\n    this.compileList(node.values)\n    this.append(')')\n  }\n\n  protected override visitPrimitiveValueList(\n    node: PrimitiveValueListNode,\n  ): void {\n    this.append('(')\n\n    const { values } = node\n    for (let i = 0; i < values.length; ++i) {\n      this.appendValue(values[i])\n\n      if (i !== values.length - 1) {\n        this.append(', ')\n      }\n    }\n\n    this.append(')')\n  }\n\n  protected override visitParens(node: ParensNode): void {\n    this.append('(')\n    this.visitNode(node.node)\n    this.append(')')\n  }\n\n  protected override visitJoin(node: JoinNode): void {\n    this.append(JOIN_TYPE_SQL[node.joinType])\n    this.append(' ')\n    this.visitNode(node.table)\n\n    if (node.on) {\n      this.append(' ')\n      this.visitNode(node.on)\n    }\n  }\n\n  protected override visitOn(node: OnNode): void {\n    this.append('on ')\n    this.visitNode(node.on)\n  }\n\n  protected override visitRaw(node: RawNode): void {\n    const { sqlFragments, parameters: params } = node\n\n    for (let i = 0; i < sqlFragments.length; ++i) {\n      this.append(sqlFragments[i])\n\n      if (params.length > i) {\n        this.visitNode(params[i])\n      }\n    }\n  }\n\n  protected override visitOperator(node: OperatorNode): void {\n    this.append(node.operator)\n  }\n\n  protected override visitTable(node: TableNode): void {\n    this.visitNode(node.table)\n  }\n\n  protected override visitSchemableIdentifier(\n    node: SchemableIdentifierNode,\n  ): void {\n    if (node.schema) {\n      this.visitNode(node.schema)\n      this.append('.')\n    }\n\n    this.visitNode(node.identifier)\n  }\n\n  protected override visitCreateTable(node: CreateTableNode): void {\n    this.append('create ')\n\n    if (node.frontModifiers?.length) {\n      this.compileList(node.frontModifiers, ' ')\n      this.append(' ')\n    }\n\n    if (node.temporary) {\n      this.append('temporary ')\n    }\n\n    this.append('table ')\n\n    if (node.ifNotExists) {\n      this.append('if not exists ')\n    }\n\n    this.visitNode(node.table)\n\n    if (!node.selectQuery) {\n      this.append(' (')\n      this.compileList([...node.columns, ...(node.constraints ?? [])])\n      this.append(')')\n    }\n\n    if (node.onCommit) {\n      this.append(' on commit ')\n      this.append(node.onCommit)\n    }\n\n    if (node.endModifiers?.length) {\n      this.append(' ')\n      this.compileList(node.endModifiers, ' ')\n    }\n\n    if (node.selectQuery) {\n      this.append(' as ')\n      this.visitNode(node.selectQuery)\n    }\n  }\n\n  protected override visitColumnDefinition(node: ColumnDefinitionNode): void {\n    if (node.ifNotExists) {\n      this.append('if not exists ')\n    }\n\n    this.visitNode(node.column)\n\n    this.append(' ')\n    this.visitNode(node.dataType)\n\n    if (node.unsigned) {\n      this.append(' unsigned')\n    }\n\n    if (node.frontModifiers && node.frontModifiers.length > 0) {\n      this.append(' ')\n      this.compileList(node.frontModifiers, ' ')\n    }\n\n    if (node.generated) {\n      this.append(' ')\n      this.visitNode(node.generated)\n    }\n\n    if (node.identity) {\n      this.append(' identity')\n    }\n\n    if (node.defaultTo) {\n      this.append(' ')\n      this.visitNode(node.defaultTo)\n    }\n\n    if (node.notNull) {\n      this.append(' not null')\n    }\n\n    if (node.unique) {\n      this.append(' unique')\n    }\n\n    if (node.nullsNotDistinct) {\n      this.append(' nulls not distinct')\n    }\n\n    if (node.primaryKey) {\n      this.append(' primary key')\n    }\n\n    if (node.autoIncrement) {\n      this.append(' ')\n      this.append(this.getAutoIncrement())\n    }\n\n    if (node.references) {\n      this.append(' ')\n      this.visitNode(node.references)\n    }\n\n    if (node.check) {\n      this.append(' ')\n      this.visitNode(node.check)\n    }\n\n    if (node.endModifiers && node.endModifiers.length > 0) {\n      this.append(' ')\n      this.compileList(node.endModifiers, ' ')\n    }\n  }\n\n  protected getAutoIncrement(): string {\n    return 'auto_increment'\n  }\n\n  protected override visitReferences(node: ReferencesNode): void {\n    this.append('references ')\n    this.visitNode(node.table)\n    this.append(' (')\n    this.compileList(node.columns)\n    this.append(')')\n\n    if (node.onDelete) {\n      this.append(' on delete ')\n      this.append(node.onDelete)\n    }\n\n    if (node.onUpdate) {\n      this.append(' on update ')\n      this.append(node.onUpdate)\n    }\n  }\n\n  protected override visitDropTable(node: DropTableNode): void {\n    this.append('drop table ')\n\n    if (node.ifExists) {\n      this.append('if exists ')\n    }\n\n    this.visitNode(node.table)\n\n    if (node.cascade) {\n      this.append(' cascade')\n    }\n  }\n\n  protected override visitDataType(node: DataTypeNode): void {\n    this.append(node.dataType)\n  }\n\n  protected override visitOrderBy(node: OrderByNode): void {\n    this.append('order by ')\n    this.compileList(node.items)\n  }\n\n  protected override visitOrderByItem(node: OrderByItemNode): void {\n    this.visitNode(node.orderBy)\n\n    if (node.collation) {\n      this.append(' ')\n      this.visitNode(node.collation)\n    }\n\n    if (node.direction) {\n      this.append(' ')\n      this.visitNode(node.direction)\n    }\n\n    if (node.nulls) {\n      this.append(' nulls ')\n      this.append(node.nulls)\n    }\n  }\n\n  protected override visitGroupBy(node: GroupByNode): void {\n    this.append('group by ')\n    this.compileList(node.items)\n  }\n\n  protected override visitGroupByItem(node: GroupByItemNode): void {\n    this.visitNode(node.groupBy)\n  }\n\n  protected override visitUpdateQuery(node: UpdateQueryNode): void {\n    const wrapInParens =\n      this.parentNode !== undefined &&\n      !ParensNode.is(this.parentNode) &&\n      !RawNode.is(this.parentNode) &&\n      !WhenNode.is(this.parentNode)\n\n    if (this.parentNode === undefined && node.explain) {\n      this.visitNode(node.explain)\n      this.append(' ')\n    }\n\n    if (wrapInParens) {\n      this.append('(')\n    }\n\n    if (node.with) {\n      this.visitNode(node.with)\n      this.append(' ')\n    }\n\n    this.append('update ')\n\n    if (node.top) {\n      this.visitNode(node.top)\n      this.append(' ')\n    }\n\n    if (node.table) {\n      this.visitNode(node.table)\n      this.append(' ')\n    }\n\n    this.append('set ')\n\n    if (node.updates) {\n      this.compileList(node.updates)\n    }\n\n    if (node.output) {\n      this.append(' ')\n      this.visitNode(node.output)\n    }\n\n    if (node.from) {\n      this.append(' ')\n      this.visitNode(node.from)\n    }\n\n    if (node.joins) {\n      if (!node.from) {\n        throw new Error(\n          \"Joins in an update query are only supported as a part of a PostgreSQL 'update set from join' query. If you want to create a MySQL 'update join set' query, see https://kysely.dev/docs/examples/update/my-sql-joins\",\n        )\n      }\n\n      this.append(' ')\n      this.compileList(node.joins, ' ')\n    }\n\n    if (node.where) {\n      this.append(' ')\n      this.visitNode(node.where)\n    }\n\n    if (node.returning) {\n      this.append(' ')\n      this.visitNode(node.returning)\n    }\n\n    if (node.orderBy) {\n      this.append(' ')\n      this.visitNode(node.orderBy)\n    }\n\n    if (node.limit) {\n      this.append(' ')\n      this.visitNode(node.limit)\n    }\n\n    if (wrapInParens) {\n      this.append(')')\n    }\n\n    if (node.endModifiers?.length) {\n      this.append(' ')\n      this.compileList(node.endModifiers, ' ')\n    }\n  }\n\n  protected override visitColumnUpdate(node: ColumnUpdateNode): void {\n    this.visitNode(node.column)\n    this.append(' = ')\n    this.visitNode(node.value)\n  }\n\n  protected override visitLimit(node: LimitNode): void {\n    this.append('limit ')\n    this.visitNode(node.limit)\n  }\n\n  protected override visitOffset(node: OffsetNode): void {\n    this.append('offset ')\n    this.visitNode(node.offset)\n  }\n\n  protected override visitOnConflict(node: OnConflictNode): void {\n    this.append('on conflict')\n\n    if (node.columns) {\n      this.append(' (')\n      this.compileList(node.columns)\n      this.append(')')\n    } else if (node.constraint) {\n      this.append(' on constraint ')\n      this.visitNode(node.constraint)\n    } else if (node.indexExpression) {\n      this.append(' (')\n      this.visitNode(node.indexExpression)\n      this.append(')')\n    }\n\n    if (node.indexWhere) {\n      this.append(' ')\n      this.visitNode(node.indexWhere)\n    }\n\n    if (node.doNothing === true) {\n      this.append(' do nothing')\n    } else if (node.updates) {\n      this.append(' do update set ')\n      this.compileList(node.updates)\n\n      if (node.updateWhere) {\n        this.append(' ')\n        this.visitNode(node.updateWhere)\n      }\n    }\n  }\n\n  protected override visitOnDuplicateKey(node: OnDuplicateKeyNode): void {\n    this.append('on duplicate key update ')\n    this.compileList(node.updates)\n  }\n\n  protected override visitCreateIndex(node: CreateIndexNode): void {\n    this.append('create ')\n\n    if (node.unique) {\n      this.append('unique ')\n    }\n\n    this.append('index ')\n\n    if (node.ifNotExists) {\n      this.append('if not exists ')\n    }\n\n    this.visitNode(node.name)\n\n    if (node.table) {\n      this.append(' on ')\n      this.visitNode(node.table)\n    }\n\n    if (node.using) {\n      this.append(' using ')\n      this.visitNode(node.using)\n    }\n\n    if (node.columns) {\n      this.append(' (')\n      this.compileList(node.columns)\n      this.append(')')\n    }\n\n    if (node.nullsNotDistinct) {\n      this.append(' nulls not distinct')\n    }\n\n    if (node.where) {\n      this.append(' ')\n      this.visitNode(node.where)\n    }\n  }\n\n  protected override visitDropIndex(node: DropIndexNode): void {\n    this.append('drop index ')\n\n    if (node.ifExists) {\n      this.append('if exists ')\n    }\n\n    this.visitNode(node.name)\n\n    if (node.table) {\n      this.append(' on ')\n      this.visitNode(node.table)\n    }\n\n    if (node.cascade) {\n      this.append(' cascade')\n    }\n  }\n\n  protected override visitCreateSchema(node: CreateSchemaNode): void {\n    this.append('create schema ')\n\n    if (node.ifNotExists) {\n      this.append('if not exists ')\n    }\n\n    this.visitNode(node.schema)\n  }\n\n  protected override visitDropSchema(node: DropSchemaNode): void {\n    this.append('drop schema ')\n\n    if (node.ifExists) {\n      this.append('if exists ')\n    }\n\n    this.visitNode(node.schema)\n\n    if (node.cascade) {\n      this.append(' cascade')\n    }\n  }\n\n  protected override visitPrimaryKeyConstraint(\n    node: PrimaryKeyConstraintNode,\n  ): void {\n    if (node.name) {\n      this.append('constraint ')\n      this.visitNode(node.name)\n      this.append(' ')\n    }\n\n    this.append('primary key (')\n    this.compileList(node.columns)\n    this.append(')')\n\n    this.buildDeferrable(node)\n  }\n\n  protected buildDeferrable(node: {\n    deferrable?: boolean\n    initiallyDeferred?: boolean\n  }): void {\n    if (node.deferrable !== undefined) {\n      if (node.deferrable) {\n        this.append(' deferrable')\n      } else {\n        this.append(' not deferrable')\n      }\n    }\n\n    if (node.initiallyDeferred !== undefined) {\n      if (node.initiallyDeferred) {\n        this.append(' initially deferred')\n      } else {\n        this.append(' initially immediate')\n      }\n    }\n  }\n\n  protected override visitUniqueConstraint(node: UniqueConstraintNode): void {\n    if (node.name) {\n      this.append('constraint ')\n      this.visitNode(node.name)\n      this.append(' ')\n    }\n\n    this.append('unique')\n\n    if (node.nullsNotDistinct) {\n      this.append(' nulls not distinct')\n    }\n\n    this.append(' (')\n    this.compileList(node.columns)\n    this.append(')')\n\n    this.buildDeferrable(node)\n  }\n\n  protected override visitCheckConstraint(node: CheckConstraintNode): void {\n    if (node.name) {\n      this.append('constraint ')\n      this.visitNode(node.name)\n      this.append(' ')\n    }\n\n    this.append('check (')\n    this.visitNode(node.expression)\n    this.append(')')\n  }\n\n  protected override visitForeignKeyConstraint(\n    node: ForeignKeyConstraintNode,\n  ): void {\n    if (node.name) {\n      this.append('constraint ')\n      this.visitNode(node.name)\n      this.append(' ')\n    }\n\n    this.append('foreign key (')\n    this.compileList(node.columns)\n    this.append(') ')\n    this.visitNode(node.references)\n\n    if (node.onDelete) {\n      this.append(' on delete ')\n      this.append(node.onDelete)\n    }\n\n    if (node.onUpdate) {\n      this.append(' on update ')\n      this.append(node.onUpdate)\n    }\n\n    this.buildDeferrable(node)\n  }\n\n  protected override visitList(node: ListNode): void {\n    this.compileList(node.items)\n  }\n\n  protected override visitWith(node: WithNode): void {\n    this.append('with ')\n\n    if (node.recursive) {\n      this.append('recursive ')\n    }\n\n    this.compileList(node.expressions)\n  }\n\n  protected override visitCommonTableExpression(\n    node: CommonTableExpressionNode,\n  ): void {\n    this.visitNode(node.name)\n    this.append(' as ')\n\n    if (isBoolean(node.materialized)) {\n      if (!node.materialized) {\n        this.append('not ')\n      }\n\n      this.append('materialized ')\n    }\n\n    this.visitNode(node.expression)\n  }\n\n  protected override visitCommonTableExpressionName(\n    node: CommonTableExpressionNameNode,\n  ): void {\n    this.visitNode(node.table)\n\n    if (node.columns) {\n      this.append('(')\n      this.compileList(node.columns)\n      this.append(')')\n    }\n  }\n\n  protected override visitAlterTable(node: AlterTableNode): void {\n    this.append('alter table ')\n    this.visitNode(node.table)\n    this.append(' ')\n\n    if (node.renameTo) {\n      this.append('rename to ')\n      this.visitNode(node.renameTo)\n    }\n\n    if (node.setSchema) {\n      this.append('set schema ')\n      this.visitNode(node.setSchema)\n    }\n\n    if (node.addConstraint) {\n      this.visitNode(node.addConstraint)\n    }\n\n    if (node.dropConstraint) {\n      this.visitNode(node.dropConstraint)\n    }\n\n    if (node.renameConstraint) {\n      this.visitNode(node.renameConstraint)\n    }\n\n    if (node.columnAlterations) {\n      this.compileColumnAlterations(node.columnAlterations)\n    }\n\n    if (node.addIndex) {\n      this.visitNode(node.addIndex)\n    }\n\n    if (node.dropIndex) {\n      this.visitNode(node.dropIndex)\n    }\n  }\n\n  protected override visitAddColumn(node: AddColumnNode): void {\n    this.append('add column ')\n    this.visitNode(node.column)\n  }\n\n  protected override visitRenameColumn(node: RenameColumnNode): void {\n    this.append('rename column ')\n    this.visitNode(node.column)\n    this.append(' to ')\n    this.visitNode(node.renameTo)\n  }\n\n  protected override visitDropColumn(node: DropColumnNode): void {\n    this.append('drop column ')\n    this.visitNode(node.column)\n  }\n\n  protected override visitAlterColumn(node: AlterColumnNode): void {\n    this.append('alter column ')\n    this.visitNode(node.column)\n    this.append(' ')\n\n    if (node.dataType) {\n      if (this.announcesNewColumnDataType()) {\n        this.append('type ')\n      }\n\n      this.visitNode(node.dataType)\n\n      if (node.dataTypeExpression) {\n        this.append('using ')\n        this.visitNode(node.dataTypeExpression)\n      }\n    }\n\n    if (node.setDefault) {\n      this.append('set default ')\n      this.visitNode(node.setDefault)\n    }\n\n    if (node.dropDefault) {\n      this.append('drop default')\n    }\n\n    if (node.setNotNull) {\n      this.append('set not null')\n    }\n\n    if (node.dropNotNull) {\n      this.append('drop not null')\n    }\n  }\n\n  protected override visitModifyColumn(node: ModifyColumnNode): void {\n    this.append('modify column ')\n    this.visitNode(node.column)\n  }\n\n  protected override visitAddConstraint(node: AddConstraintNode): void {\n    this.append('add ')\n    this.visitNode(node.constraint)\n  }\n\n  protected override visitDropConstraint(node: DropConstraintNode): void {\n    this.append('drop constraint ')\n\n    if (node.ifExists) {\n      this.append('if exists ')\n    }\n\n    this.visitNode(node.constraintName)\n\n    if (node.modifier === 'cascade') {\n      this.append(' cascade')\n    } else if (node.modifier === 'restrict') {\n      this.append(' restrict')\n    }\n  }\n\n  protected override visitRenameConstraint(node: RenameConstraintNode): void {\n    this.append('rename constraint ')\n    this.visitNode(node.oldName)\n    this.append(' to ')\n    this.visitNode(node.newName)\n  }\n\n  protected override visitSetOperation(node: SetOperationNode): void {\n    this.append(node.operator)\n    this.append(' ')\n\n    if (node.all) {\n      this.append('all ')\n    }\n\n    this.visitNode(node.expression)\n  }\n\n  protected override visitCreateView(node: CreateViewNode): void {\n    this.append('create ')\n\n    if (node.orReplace) {\n      this.append('or replace ')\n    }\n\n    if (node.materialized) {\n      this.append('materialized ')\n    }\n\n    if (node.temporary) {\n      this.append('temporary ')\n    }\n\n    this.append('view ')\n\n    if (node.ifNotExists) {\n      this.append('if not exists ')\n    }\n\n    this.visitNode(node.name)\n    this.append(' ')\n\n    if (node.columns) {\n      this.append('(')\n      this.compileList(node.columns)\n      this.append(') ')\n    }\n\n    if (node.as) {\n      this.append('as ')\n      this.visitNode(node.as)\n    }\n  }\n\n  protected override visitRefreshMaterializedView(\n    node: RefreshMaterializedViewNode,\n  ): void {\n    this.append('refresh materialized view ')\n\n    if (node.concurrently) {\n      this.append('concurrently ')\n    }\n\n    this.visitNode(node.name)\n\n    if (node.withNoData) {\n      this.append(' with no data')\n    } else {\n      this.append(' with data')\n    }\n  }\n\n  protected override visitDropView(node: DropViewNode): void {\n    this.append('drop ')\n\n    if (node.materialized) {\n      this.append('materialized ')\n    }\n\n    this.append('view ')\n\n    if (node.ifExists) {\n      this.append('if exists ')\n    }\n\n    this.visitNode(node.name)\n\n    if (node.cascade) {\n      this.append(' cascade')\n    }\n  }\n\n  protected override visitGenerated(node: GeneratedNode): void {\n    this.append('generated ')\n\n    if (node.always) {\n      this.append('always ')\n    }\n\n    if (node.byDefault) {\n      this.append('by default ')\n    }\n\n    this.append('as ')\n\n    if (node.identity) {\n      this.append('identity')\n    }\n\n    if (node.expression) {\n      this.append('(')\n      this.visitNode(node.expression)\n      this.append(')')\n    }\n\n    if (node.stored) {\n      this.append(' stored')\n    }\n  }\n\n  protected override visitDefaultValue(node: DefaultValueNode): void {\n    this.append('default ')\n    this.visitNode(node.defaultValue)\n  }\n\n  protected override visitSelectModifier(node: SelectModifierNode): void {\n    if (node.rawModifier) {\n      this.visitNode(node.rawModifier)\n    } else {\n      this.append(SELECT_MODIFIER_SQL[node.modifier!])\n    }\n\n    if (node.of) {\n      this.append(' of ')\n      this.compileList(node.of, ', ')\n    }\n  }\n\n  protected override visitCreateType(node: CreateTypeNode): void {\n    this.append('create type ')\n    this.visitNode(node.name)\n\n    if (node.enum) {\n      this.append(' as enum ')\n      this.visitNode(node.enum)\n    }\n  }\n\n  protected override visitDropType(node: DropTypeNode): void {\n    this.append('drop type ')\n\n    if (node.ifExists) {\n      this.append('if exists ')\n    }\n\n    this.visitNode(node.name)\n  }\n\n  protected override visitExplain(node: ExplainNode): void {\n    this.append('explain')\n\n    if (node.options || node.format) {\n      this.append(' ')\n      this.append(this.getLeftExplainOptionsWrapper())\n\n      if (node.options) {\n        this.visitNode(node.options)\n\n        if (node.format) {\n          this.append(this.getExplainOptionsDelimiter())\n        }\n      }\n\n      if (node.format) {\n        this.append('format')\n        this.append(this.getExplainOptionAssignment())\n        this.append(node.format)\n      }\n\n      this.append(this.getRightExplainOptionsWrapper())\n    }\n  }\n\n  protected visitDefaultInsertValue(_: DefaultInsertValueNode): void {\n    this.append('default')\n  }\n\n  protected override visitAggregateFunction(node: AggregateFunctionNode): void {\n    this.append(node.func)\n    this.append('(')\n\n    if (node.distinct) {\n      this.append('distinct ')\n    }\n\n    this.compileList(node.aggregated)\n\n    if (node.orderBy) {\n      this.append(' ')\n      this.visitNode(node.orderBy)\n    }\n\n    this.append(')')\n\n    if (node.withinGroup) {\n      this.append(' within group (')\n      this.visitNode(node.withinGroup)\n      this.append(')')\n    }\n\n    if (node.filter) {\n      this.append(' filter(')\n      this.visitNode(node.filter)\n      this.append(')')\n    }\n\n    if (node.over) {\n      this.append(' ')\n      this.visitNode(node.over)\n    }\n  }\n\n  protected override visitOver(node: OverNode): void {\n    this.append('over(')\n\n    if (node.partitionBy) {\n      this.visitNode(node.partitionBy)\n\n      if (node.orderBy) {\n        this.append(' ')\n      }\n    }\n\n    if (node.orderBy) {\n      this.visitNode(node.orderBy)\n    }\n\n    this.append(')')\n  }\n\n  protected override visitPartitionBy(node: PartitionByNode): void {\n    this.append('partition by ')\n    this.compileList(node.items)\n  }\n\n  protected override visitPartitionByItem(node: PartitionByItemNode): void {\n    this.visitNode(node.partitionBy)\n  }\n\n  protected override visitBinaryOperation(node: BinaryOperationNode): void {\n    this.visitNode(node.leftOperand)\n    this.append(' ')\n    this.visitNode(node.operator)\n    this.append(' ')\n    this.visitNode(node.rightOperand)\n  }\n\n  protected override visitUnaryOperation(node: UnaryOperationNode): void {\n    this.visitNode(node.operator)\n\n    if (!this.isMinusOperator(node.operator)) {\n      this.append(' ')\n    }\n\n    this.visitNode(node.operand)\n  }\n\n  protected isMinusOperator(node: OperationNode): node is OperatorNode {\n    return OperatorNode.is(node) && node.operator === '-'\n  }\n\n  protected override visitUsing(node: UsingNode): void {\n    this.append('using ')\n    this.compileList(node.tables)\n  }\n\n  protected override visitFunction(node: FunctionNode): void {\n    this.append(node.func)\n    this.append('(')\n    this.compileList(node.arguments)\n    this.append(')')\n  }\n\n  protected override visitCase(node: CaseNode): void {\n    this.append('case')\n\n    if (node.value) {\n      this.append(' ')\n      this.visitNode(node.value)\n    }\n\n    if (node.when) {\n      this.append(' ')\n      this.compileList(node.when, ' ')\n    }\n\n    if (node.else) {\n      this.append(' else ')\n      this.visitNode(node.else)\n    }\n\n    this.append(' end')\n\n    if (node.isStatement) {\n      this.append(' case')\n    }\n  }\n\n  protected override visitWhen(node: WhenNode): void {\n    this.append('when ')\n\n    this.visitNode(node.condition)\n\n    if (node.result) {\n      this.append(' then ')\n      this.visitNode(node.result)\n    }\n  }\n\n  protected override visitJSONReference(node: JSONReferenceNode): void {\n    this.visitNode(node.reference)\n    this.visitNode(node.traversal)\n  }\n\n  protected override visitJSONPath(node: JSONPathNode): void {\n    if (node.inOperator) {\n      this.visitNode(node.inOperator)\n    }\n\n    this.append(\"'$\")\n\n    for (const pathLeg of node.pathLegs) {\n      this.visitNode(pathLeg)\n    }\n\n    this.append(\"'\")\n  }\n\n  protected override visitJSONPathLeg(node: JSONPathLegNode): void {\n    const isArrayLocation = node.type === 'ArrayLocation'\n\n    this.append(isArrayLocation ? '[' : '.')\n\n    this.append(\n      typeof node.value === 'string'\n        ? this.sanitizeStringLiteral(node.value)\n        : String(node.value),\n    )\n\n    if (isArrayLocation) {\n      this.append(']')\n    }\n  }\n\n  protected override visitJSONOperatorChain(node: JSONOperatorChainNode): void {\n    for (let i = 0, len = node.values.length; i < len; i++) {\n      if (i === len - 1) {\n        this.visitNode(node.operator)\n      } else {\n        this.append('->')\n      }\n\n      this.visitNode(node.values[i])\n    }\n  }\n\n  protected override visitMergeQuery(node: MergeQueryNode): void {\n    if (node.with) {\n      this.visitNode(node.with)\n      this.append(' ')\n    }\n\n    this.append('merge ')\n\n    if (node.top) {\n      this.visitNode(node.top)\n      this.append(' ')\n    }\n\n    this.append('into ')\n    this.visitNode(node.into)\n\n    if (node.using) {\n      this.append(' ')\n      this.visitNode(node.using)\n    }\n\n    if (node.whens) {\n      this.append(' ')\n      this.compileList(node.whens, ' ')\n    }\n\n    if (node.returning) {\n      this.append(' ')\n      this.visitNode(node.returning)\n    }\n\n    if (node.output) {\n      this.append(' ')\n      this.visitNode(node.output)\n    }\n\n    if (node.endModifiers?.length) {\n      this.append(' ')\n      this.compileList(node.endModifiers, ' ')\n    }\n  }\n\n  protected override visitMatched(node: MatchedNode): void {\n    if (node.not) {\n      this.append('not ')\n    }\n\n    this.append('matched')\n\n    if (node.bySource) {\n      this.append(' by source')\n    }\n  }\n\n  protected override visitAddIndex(node: AddIndexNode): void {\n    this.append('add ')\n\n    if (node.unique) {\n      this.append('unique ')\n    }\n\n    this.append('index ')\n\n    this.visitNode(node.name)\n\n    if (node.columns) {\n      this.append(' (')\n      this.compileList(node.columns)\n      this.append(')')\n    }\n\n    if (node.using) {\n      this.append(' using ')\n      this.visitNode(node.using)\n    }\n  }\n\n  protected override visitCast(node: CastNode): void {\n    this.append('cast(')\n    this.visitNode(node.expression)\n    this.append(' as ')\n    this.visitNode(node.dataType)\n    this.append(')')\n  }\n\n  protected override visitFetch(node: FetchNode): void {\n    this.append('fetch next ')\n    this.visitNode(node.rowCount)\n    this.append(` rows ${node.modifier}`)\n  }\n\n  protected override visitOutput(node: OutputNode): void {\n    this.append('output ')\n    this.compileList(node.selections)\n  }\n\n  protected override visitTop(node: TopNode): void {\n    this.append(`top(${node.expression})`)\n\n    if (node.modifiers) {\n      this.append(` ${node.modifiers}`)\n    }\n  }\n\n  protected override visitOrAction(node: OrActionNode): void {\n    this.append(node.action)\n  }\n\n  protected override visitCollate(node: CollateNode): void {\n    this.append('collate ')\n    this.visitNode(node.collation)\n  }\n\n  protected append(str: string): void {\n    this.#sql += str\n  }\n\n  protected appendValue(parameter: unknown): void {\n    this.addParameter(parameter)\n    this.append(this.getCurrentParameterPlaceholder())\n  }\n\n  protected getLeftIdentifierWrapper(): string {\n    return '\"'\n  }\n\n  protected getRightIdentifierWrapper(): string {\n    return '\"'\n  }\n\n  protected getCurrentParameterPlaceholder(): string {\n    return '$' + this.numParameters\n  }\n\n  protected getLeftExplainOptionsWrapper(): string {\n    return '('\n  }\n\n  protected getExplainOptionAssignment(): string {\n    return ' '\n  }\n\n  protected getExplainOptionsDelimiter(): string {\n    return ', '\n  }\n\n  protected getRightExplainOptionsWrapper(): string {\n    return ')'\n  }\n\n  protected sanitizeIdentifier(identifier: string): string {\n    const leftWrap = this.getLeftIdentifierWrapper()\n    const rightWrap = this.getRightIdentifierWrapper()\n\n    let sanitized = ''\n    for (const c of identifier) {\n      sanitized += c\n\n      if (c === leftWrap) {\n        sanitized += leftWrap\n      } else if (c === rightWrap) {\n        sanitized += rightWrap\n      }\n    }\n\n    return sanitized\n  }\n\n  protected sanitizeStringLiteral(value: string): string {\n    return value.replace(LIT_WRAP_REGEX, \"''\")\n  }\n\n  protected addParameter(parameter: unknown): void {\n    this.#parameters.push(parameter)\n  }\n\n  protected appendImmediateValue(value: unknown): void {\n    if (isString(value)) {\n      this.appendStringLiteral(value)\n    } else if (isNumber(value) || isBoolean(value) || isBigInt(value)) {\n      this.append(value.toString())\n    } else if (isNull(value)) {\n      this.append('null')\n    } else if (isDate(value)) {\n      this.appendImmediateValue(value.toISOString())\n    } else {\n      throw new Error(`invalid immediate value ${value}`)\n    }\n  }\n\n  protected appendStringLiteral(value: string): void {\n    this.append(\"'\")\n    this.append(this.sanitizeStringLiteral(value))\n    this.append(\"'\")\n  }\n\n  protected sortSelectModifiers(\n    arr: SelectModifierNode[],\n  ): ReadonlyArray<SelectModifierNode> {\n    arr.sort((left, right) =>\n      left.modifier && right.modifier\n        ? SELECT_MODIFIER_PRIORITY[left.modifier] -\n          SELECT_MODIFIER_PRIORITY[right.modifier]\n        : 1,\n    )\n\n    return freeze(arr)\n  }\n\n  protected compileColumnAlterations(\n    columnAlterations: readonly AlterTableColumnAlterationNode[],\n  ) {\n    this.compileList(columnAlterations)\n  }\n\n  /**\n   * controls whether the dialect adds a \"type\" keyword before a column's new data\n   * type in an ALTER TABLE statement.\n   */\n  protected announcesNewColumnDataType(): boolean {\n    return true\n  }\n}\n\nconst SELECT_MODIFIER_SQL: Readonly<Record<SelectModifier, string>> = freeze({\n  ForKeyShare: 'for key share',\n  ForNoKeyUpdate: 'for no key update',\n  ForUpdate: 'for update',\n  ForShare: 'for share',\n  NoWait: 'nowait',\n  SkipLocked: 'skip locked',\n  Distinct: 'distinct',\n})\n\nconst SELECT_MODIFIER_PRIORITY: Readonly<Record<SelectModifier, number>> =\n  freeze({\n    ForKeyShare: 1,\n    ForNoKeyUpdate: 1,\n    ForUpdate: 1,\n    ForShare: 1,\n    NoWait: 2,\n    SkipLocked: 2,\n    Distinct: 0,\n  })\n\nconst JOIN_TYPE_SQL: Readonly<Record<JoinType, string>> = freeze({\n  InnerJoin: 'inner join',\n  LeftJoin: 'left join',\n  RightJoin: 'right join',\n  FullJoin: 'full join',\n  CrossJoin: 'cross join',\n  LateralInnerJoin: 'inner join lateral',\n  LateralLeftJoin: 'left join lateral',\n  LateralCrossJoin: 'cross join lateral',\n  OuterApply: 'outer apply',\n  CrossApply: 'cross apply',\n  Using: 'using',\n})\n"
  },
  {
    "path": "src/query-compiler/query-compiler.ts",
    "content": "import type { AlterTableNode } from '../operation-node/alter-table-node.js'\nimport type { CreateIndexNode } from '../operation-node/create-index-node.js'\nimport type { CreateSchemaNode } from '../operation-node/create-schema-node.js'\nimport type { CreateTableNode } from '../operation-node/create-table-node.js'\nimport type { CreateTypeNode } from '../operation-node/create-type-node.js'\nimport type { CreateViewNode } from '../operation-node/create-view-node.js'\nimport type { DropIndexNode } from '../operation-node/drop-index-node.js'\nimport type { DropSchemaNode } from '../operation-node/drop-schema-node.js'\nimport type { DropTableNode } from '../operation-node/drop-table-node.js'\nimport type { DropTypeNode } from '../operation-node/drop-type-node.js'\nimport type { DropViewNode } from '../operation-node/drop-view-node.js'\nimport type { MergeQueryNode } from '../operation-node/merge-query-node.js'\nimport type { QueryNode } from '../operation-node/query-node.js'\nimport type { RawNode } from '../operation-node/raw-node.js'\nimport type { RefreshMaterializedViewNode } from '../operation-node/refresh-materialized-view-node.js'\nimport type { QueryId } from '../util/query-id.js'\nimport type { CompiledQuery } from './compiled-query.js'\n\nexport type RootOperationNode =\n  | QueryNode\n  | CreateTableNode\n  | CreateIndexNode\n  | CreateSchemaNode\n  | CreateViewNode\n  | RefreshMaterializedViewNode\n  | DropTableNode\n  | DropIndexNode\n  | DropSchemaNode\n  | DropViewNode\n  | AlterTableNode\n  | RawNode\n  | CreateTypeNode\n  | DropTypeNode\n  | MergeQueryNode\n\n/**\n * a `QueryCompiler` compiles a query expressed as a tree of `OperationNodes` into SQL.\n */\nexport interface QueryCompiler {\n  compileQuery(node: RootOperationNode, queryId: QueryId): CompiledQuery\n}\n"
  },
  {
    "path": "src/query-creator.ts",
    "content": "import {\n  type SelectQueryBuilder,\n  createSelectQueryBuilder,\n} from './query-builder/select-query-builder.js'\nimport { InsertQueryBuilder } from './query-builder/insert-query-builder.js'\nimport { DeleteQueryBuilder } from './query-builder/delete-query-builder.js'\nimport { UpdateQueryBuilder } from './query-builder/update-query-builder.js'\nimport { DeleteQueryNode } from './operation-node/delete-query-node.js'\nimport { InsertQueryNode } from './operation-node/insert-query-node.js'\nimport { SelectQueryNode } from './operation-node/select-query-node.js'\nimport { UpdateQueryNode } from './operation-node/update-query-node.js'\nimport {\n  parseTable,\n  parseTableExpressionOrList,\n  type TableExpressionOrList,\n  type SimpleTableReference,\n  parseAliasedTable,\n} from './parser/table-parser.js'\nimport type { QueryExecutor } from './query-executor/query-executor.js'\nimport {\n  type CommonTableExpression,\n  type QueryCreatorWithCommonTableExpression,\n  type RecursiveCommonTableExpression,\n  parseCommonTableExpression,\n} from './parser/with-parser.js'\nimport { WithNode } from './operation-node/with-node.js'\nimport { createQueryId } from './util/query-id.js'\nimport { WithSchemaPlugin } from './plugin/with-schema/with-schema-plugin.js'\nimport { freeze } from './util/object-utils.js'\nimport type { InsertResult } from './query-builder/insert-result.js'\nimport type { DeleteResult } from './query-builder/delete-result.js'\nimport type { UpdateResult } from './query-builder/update-result.js'\nimport type { KyselyPlugin } from './plugin/kysely-plugin.js'\nimport type { CTEBuilderCallback } from './query-builder/cte-builder.js'\nimport {\n  type CallbackSelection,\n  type SelectArg,\n  type SelectCallback,\n  type SelectExpression,\n  type Selection,\n  parseSelectArg,\n} from './parser/select-parser.js'\nimport { MergeQueryBuilder } from './query-builder/merge-query-builder.js'\nimport { MergeQueryNode } from './operation-node/merge-query-node.js'\nimport type { MergeResult } from './query-builder/merge-result.js'\nimport type { SelectFrom } from './parser/select-from-parser.js'\nimport type { DeleteFrom } from './parser/delete-from-parser.js'\nimport type { UpdateTable } from './parser/update-parser.js'\nimport type { MergeInto } from './parser/merge-into-parser.js'\n\nexport class QueryCreator<DB> {\n  readonly #props: QueryCreatorProps\n\n  constructor(props: QueryCreatorProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Creates a `select` query builder for the given table or tables.\n   *\n   * The tables passed to this method are built as the query's `from` clause.\n   *\n   * ### Examples\n   *\n   * Create a select query for one table:\n   *\n   * ```ts\n   * db.selectFrom('person').selectAll()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\"\n   * ```\n   *\n   * Create a select query for one table with an alias:\n   *\n   * ```ts\n   * const persons = await db.selectFrom('person as p')\n   *   .select(['p.id', 'first_name'])\n   *   .execute()\n   *\n   * console.log(persons[0].id)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"p\".\"id\", \"first_name\" from \"person\" as \"p\"\n   * ```\n   *\n   * Create a select query from a subquery:\n   *\n   * ```ts\n   * const persons = await db.selectFrom(\n   *     (eb) => eb.selectFrom('person').select('person.id as identifier').as('p')\n   *   )\n   *   .select('p.identifier')\n   *   .execute()\n   *\n   * console.log(persons[0].identifier)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"p\".\"identifier\",\n   * from (\n   *   select \"person\".\"id\" as \"identifier\" from \"person\"\n   * ) as p\n   * ```\n   *\n   * Create a select query from raw sql:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const items = await db\n   *   .selectFrom(sql<{ one: number }>`(select 1 as one)`.as('q'))\n   *   .select('q.one')\n   *   .execute()\n   *\n   * console.log(items[0].one)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"q\".\"one\",\n   * from (\n   *   select 1 as one\n   * ) as q\n   * ```\n   *\n   * When you use the `sql` tag you need to also provide the result type of the\n   * raw snippet / query so that Kysely can figure out what columns are\n   * available for the rest of the query.\n   *\n   * The `selectFrom` method also accepts an array for multiple tables. All\n   * the above examples can also be used in an array.\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const items = await db.selectFrom([\n   *     'person as p',\n   *     db.selectFrom('pet').select('pet.species').as('a'),\n   *     sql<{ one: number }>`(select 1 as one)`.as('q')\n   *   ])\n   *   .select(['p.id', 'a.species', 'q.one'])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"p\".id, \"a\".\"species\", \"q\".\"one\"\n   * from\n   *   \"person\" as \"p\",\n   *   (select \"pet\".\"species\" from \"pet\") as a,\n   *   (select 1 as one) as \"q\"\n   * ```\n   */\n  selectFrom<TE extends TableExpressionOrList<DB, never>>(\n    from: TE,\n  ): SelectFrom<DB, never, TE> {\n    return createSelectQueryBuilder({\n      queryId: createQueryId(),\n      executor: this.#props.executor,\n      queryNode: SelectQueryNode.createFrom(\n        parseTableExpressionOrList(from as TableExpressionOrList<any, any>),\n        this.#props.withNode,\n      ),\n    }) as SelectFrom<DB, never, TE>\n  }\n\n  /**\n   * Creates a `select` query builder without a `from` clause.\n   *\n   * If you want to create a `select from` query, use the `selectFrom` method instead.\n   * This one can be used to create a plain `select` statement without a `from` clause.\n   *\n   * This method accepts the same inputs as {@link SelectQueryBuilder.select}. See its\n   * documentation for more examples.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db.selectNoFrom((eb) => [\n   *   eb.selectFrom('person')\n   *     .select('id')\n   *     .where('first_name', '=', 'Jennifer')\n   *     .limit(1)\n   *     .as('jennifer_id'),\n   *   eb.selectFrom('pet')\n   *     .select('id')\n   *     .where('name', '=', 'Doggo')\n   *     .limit(1)\n   *     .as('doggo_id')\n   * ])\n   * .executeTakeFirstOrThrow()\n   *\n   * console.log(result.jennifer_id)\n   * console.log(result.doggo_id)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select (\n   *   select \"id\"\n   *   from \"person\"\n   *   where \"first_name\" = $1\n   *   limit $2\n   * ) as \"jennifer_id\", (\n   *   select \"id\"\n   *   from \"pet\"\n   *   where \"name\" = $3\n   *   limit $4\n   * ) as \"doggo_id\"\n   * ```\n   */\n  selectNoFrom<SE extends SelectExpression<DB, never>>(\n    selections: ReadonlyArray<SE>,\n  ): SelectQueryBuilder<DB, never, Selection<DB, never, SE>>\n\n  selectNoFrom<CB extends SelectCallback<DB, never>>(\n    callback: CB,\n  ): SelectQueryBuilder<DB, never, CallbackSelection<DB, never, CB>>\n\n  selectNoFrom<SE extends SelectExpression<DB, never>>(\n    selection: SE,\n  ): SelectQueryBuilder<DB, never, Selection<DB, never, SE>>\n\n  selectNoFrom<SE extends SelectExpression<DB, never>>(\n    selection: SelectArg<DB, never, SE>,\n  ): SelectQueryBuilder<DB, never, Selection<DB, never, SE>> {\n    return createSelectQueryBuilder({\n      queryId: createQueryId(),\n      executor: this.#props.executor,\n      queryNode: SelectQueryNode.cloneWithSelections(\n        SelectQueryNode.create(this.#props.withNode),\n        parseSelectArg(selection as any),\n      ),\n    })\n  }\n\n  /**\n   * Creates an insert query.\n   *\n   * The return value of this query is an instance of {@link InsertResult}. {@link InsertResult}\n   * has the {@link InsertResult.insertId | insertId} field that holds the auto incremented id of\n   * the inserted row if the db returned one.\n   *\n   * See the {@link InsertQueryBuilder.values | values} method for more info and examples. Also see\n   * the {@link ReturningInterface.returning | returning} method for a way to return columns\n   * on supported databases like PostgreSQL.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db\n   *   .insertInto('person')\n   *   .values({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   })\n   *   .executeTakeFirst()\n   *\n   * console.log(result.insertId)\n   * ```\n   *\n   * Some databases like PostgreSQL support the `returning` method:\n   *\n   * ```ts\n   * const { id } = await db\n   *   .insertInto('person')\n   *   .values({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   })\n   *   .returning('id')\n   *   .executeTakeFirstOrThrow()\n   * ```\n   */\n  insertInto<T extends keyof DB & string>(\n    table: T,\n  ): InsertQueryBuilder<DB, T, InsertResult> {\n    return new InsertQueryBuilder({\n      queryId: createQueryId(),\n      executor: this.#props.executor,\n      queryNode: InsertQueryNode.create(\n        parseTable(table),\n        this.#props.withNode,\n      ),\n    })\n  }\n\n  /**\n   * Creates a \"replace into\" query.\n   *\n   * This is only supported by some dialects like MySQL or SQLite.\n   *\n   * Similar to MySQL's {@link InsertQueryBuilder.onDuplicateKeyUpdate} that deletes\n   * and inserts values on collision instead of updating existing rows.\n   *\n   * An alias of SQLite's {@link InsertQueryBuilder.orReplace}.\n   *\n   * The return value of this query is an instance of {@link InsertResult}. {@link InsertResult}\n   * has the {@link InsertResult.insertId | insertId} field that holds the auto incremented id of\n   * the inserted row if the db returned one.\n   *\n   * See the {@link InsertQueryBuilder.values | values} method for more info and examples.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db\n   *   .replaceInto('person')\n   *   .values({\n   *     first_name: 'Jennifer',\n   *     last_name: 'Aniston'\n   *   })\n   *   .executeTakeFirstOrThrow()\n   *\n   * console.log(result.insertId)\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * replace into `person` (`first_name`, `last_name`) values (?, ?)\n   * ```\n   */\n  replaceInto<T extends keyof DB & string>(\n    table: T,\n  ): InsertQueryBuilder<DB, T, InsertResult> {\n    return new InsertQueryBuilder({\n      queryId: createQueryId(),\n      executor: this.#props.executor,\n      queryNode: InsertQueryNode.create(\n        parseTable(table),\n        this.#props.withNode,\n        true,\n      ),\n    })\n  }\n\n  /**\n   * Creates a delete query.\n   *\n   * See the {@link DeleteQueryBuilder.where} method for examples on how to specify\n   * a where clause for the delete operation.\n   *\n   * The return value of the query is an instance of {@link DeleteResult}.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"delete\", \"Single row\", 10) -->\n   *\n   * Delete a single row:\n   *\n   * ```ts\n   * const result = await db\n   *   .deleteFrom('person')\n   *   .where('person.id', '=', 1)\n   *   .executeTakeFirst()\n   *\n   * console.log(result.numDeletedRows)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * delete from \"person\" where \"person\".\"id\" = $1\n   * ```\n   *\n   * Some databases such as MySQL support deleting from multiple tables:\n   *\n   * ```ts\n   * const result = await db\n   *   .deleteFrom(['person', 'pet'])\n   *   .using('person')\n   *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n   *   .where('person.id', '=', 1)\n   *   .executeTakeFirst()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * delete from `person`, `pet`\n   * using `person`\n   * inner join `pet` on `pet`.`owner_id` = `person`.`id`\n   * where `person`.`id` = ?\n   * ```\n   */\n  deleteFrom<TE extends TableExpressionOrList<DB, never>>(\n    from: TE,\n  ): DeleteFrom<DB, TE> {\n    return new DeleteQueryBuilder({\n      queryId: createQueryId(),\n      executor: this.#props.executor,\n      queryNode: DeleteQueryNode.create(\n        parseTableExpressionOrList(from as TableExpressionOrList<any, any>),\n        this.#props.withNode,\n      ),\n    }) as DeleteFrom<DB, TE>\n  }\n\n  /**\n   * Creates an update query.\n   *\n   * See the {@link UpdateQueryBuilder.where} method for examples on how to specify\n   * a where clause for the update operation.\n   *\n   * See the {@link UpdateQueryBuilder.set} method for examples on how to\n   * specify the updates.\n   *\n   * The return value of the query is an {@link UpdateResult}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const result = await db\n   *   .updateTable('person')\n   *   .set({ first_name: 'Jennifer' })\n   *   .where('person.id', '=', 1)\n   *   .executeTakeFirst()\n   *\n   * console.log(result.numUpdatedRows)\n   * ```\n   */\n  updateTable<TE extends TableExpressionOrList<DB, never>>(\n    tables: TE,\n  ): UpdateTable<DB, TE> {\n    return new UpdateQueryBuilder({\n      queryId: createQueryId(),\n      executor: this.#props.executor,\n      queryNode: UpdateQueryNode.create(\n        parseTableExpressionOrList(tables as TableExpressionOrList<any, any>),\n        this.#props.withNode,\n      ),\n    }) as UpdateTable<DB, TE>\n  }\n\n  /**\n   * Creates a merge query.\n   *\n   * The return value of the query is a {@link MergeResult}.\n   *\n   * See the {@link MergeQueryBuilder.using} method for examples on how to specify\n   * the other table.\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"merge\", \"Source row existence\", 10) -->\n   *\n   * Update a target column based on the existence of a source row:\n   *\n   * ```ts\n   * const result = await db\n   *   .mergeInto('person as target')\n   *   .using('pet as source', 'source.owner_id', 'target.id')\n   *   .whenMatchedAnd('target.has_pets', '!=', 'Y')\n   *   .thenUpdateSet({ has_pets: 'Y' })\n   *   .whenNotMatchedBySourceAnd('target.has_pets', '=', 'Y')\n   *   .thenUpdateSet({ has_pets: 'N' })\n   *   .executeTakeFirstOrThrow()\n   *\n   * console.log(result.numChangedRows)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"person\"\n   * using \"pet\"\n   * on \"pet\".\"owner_id\" = \"person\".\"id\"\n   * when matched and \"has_pets\" != $1\n   * then update set \"has_pets\" = $2\n   * when not matched by source and \"has_pets\" = $3\n   * then update set \"has_pets\" = $4\n   * ```\n   *\n   * <!-- siteExample(\"merge\", \"Temporary changes table\", 20) -->\n   *\n   * Merge new entries from a temporary changes table:\n   *\n   * ```ts\n   * const result = await db\n   *   .mergeInto('wine as target')\n   *   .using(\n   *     'wine_stock_change as source',\n   *     'source.wine_name',\n   *     'target.name',\n   *   )\n   *   .whenNotMatchedAnd('source.stock_delta', '>', 0)\n   *   .thenInsertValues(({ ref }) => ({\n   *     name: ref('source.wine_name'),\n   *     stock: ref('source.stock_delta'),\n   *   }))\n   *   .whenMatchedAnd(\n   *     (eb) => eb('target.stock', '+', eb.ref('source.stock_delta')),\n   *     '>',\n   *     0,\n   *   )\n   *   .thenUpdateSet('stock', (eb) =>\n   *     eb('target.stock', '+', eb.ref('source.stock_delta')),\n   *   )\n   *   .whenMatched()\n   *   .thenDelete()\n   *   .executeTakeFirstOrThrow()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * merge into \"wine\" as \"target\"\n   * using \"wine_stock_change\" as \"source\"\n   * on \"source\".\"wine_name\" = \"target\".\"name\"\n   * when not matched and \"source\".\"stock_delta\" > $1\n   * then insert (\"name\", \"stock\") values (\"source\".\"wine_name\", \"source\".\"stock_delta\")\n   * when matched and \"target\".\"stock\" + \"source\".\"stock_delta\" > $2\n   * then update set \"stock\" = \"target\".\"stock\" + \"source\".\"stock_delta\"\n   * when matched\n   * then delete\n   * ```\n   */\n  mergeInto<TR extends SimpleTableReference<DB>>(\n    targetTable: TR,\n  ): MergeInto<DB, TR> {\n    return new MergeQueryBuilder({\n      queryId: createQueryId(),\n      executor: this.#props.executor,\n      queryNode: MergeQueryNode.create(\n        parseAliasedTable(targetTable),\n        this.#props.withNode,\n      ),\n    }) as MergeInto<DB, TR>\n  }\n\n  /**\n   * Creates a `with` query (Common Table Expression).\n   *\n   * ### Examples\n   *\n   * <!-- siteExample(\"cte\", \"Simple selects\", 10) -->\n   *\n   * Common table expressions (CTE) are a great way to modularize complex queries.\n   * Essentially they allow you to run multiple separate queries within a\n   * single roundtrip to the DB.\n   *\n   * Since CTEs are a part of the main query, query optimizers inside DB\n   * engines are able to optimize the overall query. For example, postgres\n   * is able to inline the CTEs inside the using queries if it decides it's\n   * faster.\n   *\n   * ```ts\n   * const result = await db\n   *   // Create a CTE called `jennifers` that selects all\n   *   // persons named 'Jennifer'.\n   *   .with('jennifers', (db) => db\n   *     .selectFrom('person')\n   *     .where('first_name', '=', 'Jennifer')\n   *     .select(['id', 'age'])\n   *   )\n   *   // Select all rows from the `jennifers` CTE and\n   *   // further filter it.\n   *   .with('adult_jennifers', (db) => db\n   *     .selectFrom('jennifers')\n   *     .where('age', '>', 18)\n   *     .select(['id', 'age'])\n   *   )\n   *   // Finally select all adult jennifers that are\n   *   // also younger than 60.\n   *   .selectFrom('adult_jennifers')\n   *   .where('age', '<', 60)\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * <!-- siteExample(\"cte\", \"Inserts, updates and deletions\", 20) -->\n   *\n   * Some databases like postgres also allow you to run other queries than selects\n   * in CTEs. On these databases CTEs are extremely powerful:\n   *\n   * ```ts\n   * const result = await db\n   *   .with('new_person', (db) => db\n   *     .insertInto('person')\n   *     .values({\n   *       first_name: 'Jennifer',\n   *       age: 35,\n   *     })\n   *     .returning('id')\n   *   )\n   *   .with('new_pet', (db) => db\n   *     .insertInto('pet')\n   *     .values({\n   *       name: 'Doggo',\n   *       species: 'dog',\n   *       is_favorite: true,\n   *       // Use the id of the person we just inserted.\n   *       owner_id: db\n   *         .selectFrom('new_person')\n   *         .select('id')\n   *     })\n   *     .returning('id')\n   *   )\n   *   .selectFrom(['new_person', 'new_pet'])\n   *   .select([\n   *     'new_person.id as person_id',\n   *     'new_pet.id as pet_id'\n   *   ])\n   *   .execute()\n   * ```\n   *\n   * The CTE name can optionally specify column names in addition to\n   * a name. In that case Kysely requires the expression to retun\n   * rows with the same columns.\n   *\n   * ```ts\n   * await db\n   *   .with('jennifers(id, age)', (db) => db\n   *     .selectFrom('person')\n   *     .where('first_name', '=', 'Jennifer')\n   *     // This is ok since we return columns with the same\n   *     // names as specified by `jennifers(id, age)`.\n   *     .select(['id', 'age'])\n   *   )\n   *   .selectFrom('jennifers')\n   *   .selectAll()\n   *   .execute()\n   * ```\n   *\n   * The first argument can also be a callback. The callback is passed\n   * a `CTEBuilder` instance that can be used to configure the CTE:\n   *\n   * ```ts\n   * await db\n   *   .with(\n   *     (cte) => cte('jennifers').materialized(),\n   *     (db) => db\n   *       .selectFrom('person')\n   *       .where('first_name', '=', 'Jennifer')\n   *       .select(['id', 'age'])\n   *   )\n   *   .selectFrom('jennifers')\n   *   .selectAll()\n   *   .execute()\n   * ```\n   */\n  with<N extends string, E extends CommonTableExpression<DB, N>>(\n    nameOrBuilder: N | CTEBuilderCallback<N>,\n    expression: E,\n  ): QueryCreatorWithCommonTableExpression<DB, N, E> {\n    const cte = parseCommonTableExpression(nameOrBuilder, expression as any)\n\n    return new QueryCreator({\n      ...this.#props,\n      withNode: this.#props.withNode\n        ? WithNode.cloneWithExpression(this.#props.withNode, cte)\n        : WithNode.create(cte),\n    })\n  }\n\n  /**\n   * Creates a recursive `with` query (Common Table Expression).\n   *\n   * Note that recursiveness is a property of the whole `with` statement.\n   * You cannot have recursive and non-recursive CTEs in a same `with` statement.\n   * Therefore the recursiveness is determined by the **first** `with` or\n   * `withRecusive` call you make.\n   *\n   * See the {@link with} method for examples and more documentation.\n   */\n  withRecursive<\n    N extends string,\n    E extends RecursiveCommonTableExpression<DB, N>,\n  >(\n    nameOrBuilder: N | CTEBuilderCallback<N>,\n    expression: E,\n  ): QueryCreatorWithCommonTableExpression<DB, N, E> {\n    const cte = parseCommonTableExpression(nameOrBuilder, expression)\n\n    return new QueryCreator({\n      ...this.#props,\n      withNode: this.#props.withNode\n        ? WithNode.cloneWithExpression(this.#props.withNode, cte)\n        : WithNode.create(cte, { recursive: true }),\n    })\n  }\n\n  /**\n   * Returns a copy of this query creator instance with the given plugin installed.\n   */\n  withPlugin(plugin: KyselyPlugin): QueryCreator<DB> {\n    return new QueryCreator({\n      ...this.#props,\n      executor: this.#props.executor.withPlugin(plugin),\n    })\n  }\n\n  /**\n   * Returns a copy of this query creator instance without any plugins.\n   */\n  withoutPlugins(): QueryCreator<DB> {\n    return new QueryCreator({\n      ...this.#props,\n      executor: this.#props.executor.withoutPlugins(),\n    })\n  }\n\n  /**\n   * Sets the schema to be used for all table references that don't explicitly\n   * specify a schema.\n   *\n   * This only affects the query created through the builder returned from\n   * this method and doesn't modify the `db` instance.\n   *\n   * See [this recipe](https://github.com/kysely-org/kysely/blob/master/site/docs/recipes/0007-schemas.md)\n   * for a more detailed explanation.\n   *\n   * ### Examples\n   *\n   * ```\n   * await db\n   *   .withSchema('mammals')\n   *   .selectFrom('pet')\n   *   .selectAll()\n   *   .innerJoin('public.person', 'public.person.id', 'pet.owner_id')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"mammals\".\"pet\"\n   * inner join \"public\".\"person\"\n   * on \"public\".\"person\".\"id\" = \"mammals\".\"pet\".\"owner_id\"\n   * ```\n   *\n   * `withSchema` is smart enough to not add schema for aliases,\n   * common table expressions or other places where the schema\n   * doesn't belong to:\n   *\n   * ```\n   * await db\n   *   .withSchema('mammals')\n   *   .selectFrom('pet as p')\n   *   .select('p.name')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"p\".\"name\" from \"mammals\".\"pet\" as \"p\"\n   * ```\n   */\n  withSchema(schema: string): QueryCreator<DB> {\n    return new QueryCreator({\n      ...this.#props,\n      executor: this.#props.executor.withPluginAtFront(\n        new WithSchemaPlugin(schema),\n      ),\n    })\n  }\n}\n\nexport interface QueryCreatorProps {\n  readonly executor: QueryExecutor\n  readonly withNode?: WithNode\n}\n"
  },
  {
    "path": "src/query-executor/default-query-executor.ts",
    "content": "import type { ConnectionProvider } from '../driver/connection-provider.js'\nimport type { DatabaseConnection } from '../driver/database-connection.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type {\n  RootOperationNode,\n  QueryCompiler,\n} from '../query-compiler/query-compiler.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport { QueryExecutorBase } from './query-executor-base.js'\nimport type { DialectAdapter } from '../dialect/dialect-adapter.js'\nimport type { QueryId } from '../util/query-id.js'\n\nexport class DefaultQueryExecutor extends QueryExecutorBase {\n  #compiler: QueryCompiler\n  #adapter: DialectAdapter\n  #connectionProvider: ConnectionProvider\n\n  constructor(\n    compiler: QueryCompiler,\n    adapter: DialectAdapter,\n    connectionProvider: ConnectionProvider,\n    plugins: KyselyPlugin[] = [],\n  ) {\n    super(plugins)\n\n    this.#compiler = compiler\n    this.#adapter = adapter\n    this.#connectionProvider = connectionProvider\n  }\n\n  get adapter(): DialectAdapter {\n    return this.#adapter\n  }\n\n  compileQuery(node: RootOperationNode, queryId: QueryId): CompiledQuery {\n    return this.#compiler.compileQuery(node, queryId)\n  }\n\n  provideConnection<T>(\n    consumer: (connection: DatabaseConnection) => Promise<T>,\n  ): Promise<T> {\n    return this.#connectionProvider.provideConnection(consumer)\n  }\n\n  withPlugins(plugins: ReadonlyArray<KyselyPlugin>): DefaultQueryExecutor {\n    return new DefaultQueryExecutor(\n      this.#compiler,\n      this.#adapter,\n      this.#connectionProvider,\n      [...this.plugins, ...plugins],\n    )\n  }\n\n  withPlugin(plugin: KyselyPlugin): DefaultQueryExecutor {\n    return new DefaultQueryExecutor(\n      this.#compiler,\n      this.#adapter,\n      this.#connectionProvider,\n      [...this.plugins, plugin],\n    )\n  }\n\n  withPluginAtFront(plugin: KyselyPlugin): DefaultQueryExecutor {\n    return new DefaultQueryExecutor(\n      this.#compiler,\n      this.#adapter,\n      this.#connectionProvider,\n      [plugin, ...this.plugins],\n    )\n  }\n\n  withConnectionProvider(\n    connectionProvider: ConnectionProvider,\n  ): DefaultQueryExecutor {\n    return new DefaultQueryExecutor(\n      this.#compiler,\n      this.#adapter,\n      connectionProvider,\n      [...this.plugins],\n    )\n  }\n\n  withoutPlugins(): DefaultQueryExecutor {\n    return new DefaultQueryExecutor(\n      this.#compiler,\n      this.#adapter,\n      this.#connectionProvider,\n      [],\n    )\n  }\n}\n"
  },
  {
    "path": "src/query-executor/noop-query-executor.ts",
    "content": "import type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport type { DialectAdapter } from '../dialect/dialect-adapter.js'\nimport { QueryExecutorBase } from './query-executor-base.js'\n\n/**\n * A {@link QueryExecutor} subclass that can be used when you don't\n * have a {@link QueryCompiler}, {@link ConnectionProvider} or any\n * other needed things to actually execute queries.\n */\nexport class NoopQueryExecutor extends QueryExecutorBase {\n  get adapter(): DialectAdapter {\n    throw new Error('this query cannot be compiled to SQL')\n  }\n\n  compileQuery(): CompiledQuery {\n    throw new Error('this query cannot be compiled to SQL')\n  }\n\n  provideConnection<T>(): Promise<T> {\n    throw new Error('this query cannot be executed')\n  }\n\n  withConnectionProvider(): NoopQueryExecutor {\n    throw new Error('this query cannot have a connection provider')\n  }\n\n  withPlugin(plugin: KyselyPlugin): NoopQueryExecutor {\n    return new NoopQueryExecutor([...this.plugins, plugin])\n  }\n\n  withPlugins(plugins: ReadonlyArray<KyselyPlugin>): NoopQueryExecutor {\n    return new NoopQueryExecutor([...this.plugins, ...plugins])\n  }\n\n  withPluginAtFront(plugin: KyselyPlugin): NoopQueryExecutor {\n    return new NoopQueryExecutor([plugin, ...this.plugins])\n  }\n\n  withoutPlugins(): NoopQueryExecutor {\n    return new NoopQueryExecutor([])\n  }\n}\n\nexport const NOOP_QUERY_EXECUTOR: NoopQueryExecutor = new NoopQueryExecutor()\n"
  },
  {
    "path": "src/query-executor/query-executor-base.ts",
    "content": "import type { ConnectionProvider } from '../driver/connection-provider.js'\nimport type {\n  DatabaseConnection,\n  QueryResult,\n} from '../driver/database-connection.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { RootOperationNode } from '../query-compiler/query-compiler.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { QueryId } from '../util/query-id.js'\nimport type { DialectAdapter } from '../dialect/dialect-adapter.js'\nimport type { QueryExecutor } from './query-executor.js'\nimport { provideControlledConnection } from '../util/provide-controlled-connection.js'\nimport { logOnce } from '../util/log-once.js'\n\nconst NO_PLUGINS: ReadonlyArray<KyselyPlugin> = freeze([])\n\nexport abstract class QueryExecutorBase implements QueryExecutor {\n  readonly #plugins: ReadonlyArray<KyselyPlugin>\n\n  constructor(plugins: ReadonlyArray<KyselyPlugin> = NO_PLUGINS) {\n    this.#plugins = plugins\n  }\n\n  abstract get adapter(): DialectAdapter\n\n  get plugins(): ReadonlyArray<KyselyPlugin> {\n    return this.#plugins\n  }\n\n  transformQuery<T extends RootOperationNode>(node: T, queryId: QueryId): T {\n    for (const plugin of this.#plugins) {\n      const transformedNode = plugin.transformQuery({ node, queryId })\n\n      // We need to do a runtime check here. There is no good way\n      // to write types that enforce this constraint.\n      if (transformedNode.kind === node.kind) {\n        node = transformedNode as T\n      } else {\n        throw new Error(\n          [\n            `KyselyPlugin.transformQuery must return a node`,\n            `of the same kind that was given to it.`,\n            `The plugin was given a ${node.kind}`,\n            `but it returned a ${transformedNode.kind}`,\n          ].join(' '),\n        )\n      }\n    }\n\n    return node\n  }\n\n  abstract compileQuery(\n    node: RootOperationNode,\n    queryId: QueryId,\n  ): CompiledQuery\n\n  abstract provideConnection<T>(\n    consumer: (connection: DatabaseConnection) => Promise<T>,\n  ): Promise<T>\n\n  async executeQuery<R>(compiledQuery: CompiledQuery): Promise<QueryResult<R>> {\n    return await this.provideConnection(async (connection) => {\n      const result = await connection.executeQuery(compiledQuery)\n\n      if ('numUpdatedOrDeletedRows' in result) {\n        logOnce(\n          'kysely:warning: outdated driver/plugin detected! `QueryResult.numUpdatedOrDeletedRows` has been replaced with `QueryResult.numAffectedRows`.',\n        )\n      }\n\n      return await this.#transformResult(result, compiledQuery.queryId)\n    })\n  }\n\n  async *stream<R>(\n    compiledQuery: CompiledQuery,\n    chunkSize: number,\n  ): AsyncIterableIterator<QueryResult<R>> {\n    const { connection, release } = await provideControlledConnection(this)\n\n    try {\n      for await (const result of connection.streamQuery(\n        compiledQuery,\n        chunkSize,\n      )) {\n        yield await this.#transformResult(result, compiledQuery.queryId)\n      }\n    } finally {\n      release()\n    }\n  }\n\n  abstract withConnectionProvider(\n    connectionProvider: ConnectionProvider,\n  ): QueryExecutorBase\n\n  abstract withPlugin(plugin: KyselyPlugin): QueryExecutorBase\n  abstract withPlugins(plugin: ReadonlyArray<KyselyPlugin>): QueryExecutorBase\n  abstract withPluginAtFront(plugin: KyselyPlugin): QueryExecutorBase\n  abstract withoutPlugins(): QueryExecutorBase\n\n  async #transformResult<T>(\n    result: QueryResult<any>,\n    queryId: QueryId,\n  ): Promise<QueryResult<T>> {\n    for (const plugin of this.#plugins) {\n      result = await plugin.transformResult({ result, queryId })\n    }\n\n    return result\n  }\n}\n"
  },
  {
    "path": "src/query-executor/query-executor-provider.ts",
    "content": "import type { QueryExecutor } from './query-executor.js'\n\n/**\n * @internal\n * @private\n */\nexport interface QueryExecutorProvider {\n  getExecutor(): QueryExecutor\n}\n"
  },
  {
    "path": "src/query-executor/query-executor.ts",
    "content": "import type { ConnectionProvider } from '../driver/connection-provider.js'\nimport type { QueryResult } from '../driver/database-connection.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { RootOperationNode } from '../query-compiler/query-compiler.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport type { QueryId } from '../util/query-id.js'\nimport type { DialectAdapter } from '../dialect/dialect-adapter.js'\n\n/**\n * This interface abstracts away the details of how to compile a query into SQL\n * and execute it. Instead of passing around all those details, {@link SelectQueryBuilder}\n * and other classes that execute queries can just pass around and instance of\n * `QueryExecutor`.\n */\nexport interface QueryExecutor extends ConnectionProvider {\n  /**\n   * Returns the adapter for the current dialect.\n   */\n  get adapter(): DialectAdapter\n\n  /**\n   * Returns all installed plugins.\n   */\n  get plugins(): ReadonlyArray<KyselyPlugin>\n\n  /**\n   * Given the query the user has built (expressed as an operation node tree)\n   * this method runs it through all plugins' `transformQuery` methods and\n   * returns the result.\n   */\n  transformQuery<T extends RootOperationNode>(node: T, queryId: QueryId): T\n\n  /**\n   * Compiles the transformed query into SQL. You usually want to pass\n   * the output of {@link transformQuery} into this method but you can\n   * compile any query using this method.\n   */\n  compileQuery<R = unknown>(\n    node: RootOperationNode,\n    queryId: QueryId,\n  ): CompiledQuery<R>\n\n  /**\n   * Executes a compiled query and runs the result through all plugins'\n   * `transformResult` method.\n   */\n  executeQuery<R>(compiledQuery: CompiledQuery<R>): Promise<QueryResult<R>>\n\n  /**\n   * Executes a compiled query and runs the result through all plugins'\n   * `transformResult` method. Results are streamead instead of loaded\n   * at once.\n   */\n  stream<R>(\n    compiledQuery: CompiledQuery<R>,\n    /**\n     * How many rows should be pulled from the database at once. Supported\n     * only by the postgres driver.\n     */\n    chunkSize: number,\n  ): AsyncIterableIterator<QueryResult<R>>\n\n  /**\n   * Returns a copy of this executor with a new connection provider.\n   */\n  withConnectionProvider(connectionProvider: ConnectionProvider): QueryExecutor\n\n  /**\n   * Returns a copy of this executor with a plugin added as the\n   * last plugin.\n   */\n  withPlugin(plugin: KyselyPlugin): QueryExecutor\n\n  /**\n   * Returns a copy of this executor with a list of plugins added\n   * as the last plugins.\n   */\n  withPlugins(plugin: ReadonlyArray<KyselyPlugin>): QueryExecutor\n\n  /**\n   * Returns a copy of this executor with a plugin added as the\n   * first plugin.\n   */\n  withPluginAtFront(plugin: KyselyPlugin): QueryExecutor\n\n  /**\n   * Returns a copy of this executor without any plugins.\n   */\n  withoutPlugins(): QueryExecutor\n}\n"
  },
  {
    "path": "src/raw-builder/raw-builder.ts",
    "content": "import type { QueryResult } from '../driver/database-connection.js'\nimport { AliasNode } from '../operation-node/alias-node.js'\nimport type { RawNode } from '../operation-node/raw-node.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport { NOOP_QUERY_EXECUTOR } from '../query-executor/noop-query-executor.js'\nimport type { QueryExecutorProvider } from '../query-executor/query-executor-provider.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport type {\n  AliasableExpression,\n  AliasedExpression,\n  Expression,\n} from '../expression/expression.js'\nimport { isOperationNodeSource } from '../operation-node/operation-node-source.js'\n\n/**\n * An instance of this class can be used to create raw SQL snippets or queries.\n *\n * You shouldn't need to create `RawBuilder` instances directly. Instead you should\n * use the {@link sql} template tag.\n */\nexport interface RawBuilder<O> extends AliasableExpression<O> {\n  get isRawBuilder(): true\n\n  /**\n   * Returns an aliased version of the SQL expression.\n   *\n   * In addition to slapping `as \"the_alias\"` to the end of the SQL,\n   * this method also provides strict typing:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const result = await db\n   *   .selectFrom('person')\n   *   .select(\n   *     sql<string>`concat(first_name, ' ', last_name)`.as('full_name')\n   *   )\n   *   .executeTakeFirstOrThrow()\n   *\n   * // `full_name: string` field exists in the result type.\n   * console.log(result.full_name)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select concat(first_name, ' ', last_name) as \"full_name\"\n   * from \"person\"\n   * ```\n   *\n   * You can also pass in a raw SQL snippet but in that case you must\n   * provide the alias as the only type argument:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const values = sql<{ a: number, b: string }>`(values (1, 'foo'))`\n   *\n   * // The alias is `t(a, b)` which specifies the column names\n   * // in addition to the table name. We must tell kysely that\n   * // columns of the table can be referenced through `t`\n   * // by providing an explicit type argument.\n   * const aliasedValues = values.as<'t'>(sql`t(a, b)`)\n   *\n   * await db\n   *   .insertInto('person')\n   *   .columns(['first_name', 'last_name'])\n   *   .expression(\n   *     db.selectFrom(aliasedValues).select(['t.a', 't.b'])\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * insert into \"person\" (\"first_name\", \"last_name\")\n   * from (values (1, 'foo')) as t(a, b)\n   * select \"t\".\"a\", \"t\".\"b\"\n   * ```\n   */\n  as<A extends string>(alias: A): AliasedRawBuilder<O, A>\n  as<A extends string>(alias: Expression<any>): AliasedRawBuilder<O, A>\n\n  /**\n   * Change the output type of the raw expression.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of this `RawBuilder` with a new output type.\n   */\n  $castTo<C>(): RawBuilder<C>\n\n  /**\n   * Omit null from the expression's type.\n   *\n   * This function can be useful in cases where you know an expression can't be\n   * null, but Kysely is unable to infer it.\n   *\n   * This method call doesn't change the SQL in any way. This methods simply\n   * returns a copy of `this` with a new output type.\n   */\n  $notNull(): RawBuilder<Exclude<O, null>>\n\n  /**\n   * Adds a plugin for this SQL snippet.\n   */\n  withPlugin(plugin: KyselyPlugin): RawBuilder<O>\n\n  /**\n   * Compiles the builder to a `CompiledQuery`.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const compiledQuery = sql`select * from ${sql.table('person')}`.compile(db)\n   * console.log(compiledQuery.sql)\n   * ```\n   */\n  compile(executorProvider: QueryExecutorProvider): CompiledQuery<O>\n\n  /**\n   * Executes the raw query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const result = await sql`select * from ${sql.table('person')}`.execute(db)\n   * ```\n   */\n  execute(executorProvider: QueryExecutorProvider): Promise<QueryResult<O>>\n\n  toOperationNode(): RawNode\n}\n\nclass RawBuilderImpl<O> implements RawBuilder<O> {\n  readonly #props: RawBuilderProps\n\n  constructor(props: RawBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  get expressionType(): O | undefined {\n    return undefined\n  }\n\n  get isRawBuilder(): true {\n    return true\n  }\n\n  as(alias: string | Expression<unknown>): AliasedRawBuilder<O, string> {\n    return new AliasedRawBuilderImpl(this, alias)\n  }\n\n  $castTo<C>(): RawBuilder<C> {\n    return new RawBuilderImpl({ ...this.#props })\n  }\n\n  $notNull(): RawBuilder<Exclude<O, null>> {\n    return new RawBuilderImpl(this.#props)\n  }\n\n  withPlugin(plugin: KyselyPlugin): RawBuilder<O> {\n    return new RawBuilderImpl({\n      ...this.#props,\n      plugins:\n        this.#props.plugins !== undefined\n          ? freeze([...this.#props.plugins, plugin])\n          : freeze([plugin]),\n    })\n  }\n\n  toOperationNode(): RawNode {\n    return this.#toOperationNode(this.#getExecutor())\n  }\n\n  compile(executorProvider: QueryExecutorProvider): CompiledQuery<O> {\n    return this.#compile(this.#getExecutor(executorProvider))\n  }\n\n  async execute(\n    executorProvider: QueryExecutorProvider,\n  ): Promise<QueryResult<O>> {\n    const executor = this.#getExecutor(executorProvider)\n\n    return executor.executeQuery<O>(this.#compile(executor))\n  }\n\n  #getExecutor(executorProvider?: QueryExecutorProvider): QueryExecutor {\n    const executor =\n      executorProvider !== undefined\n        ? executorProvider.getExecutor()\n        : NOOP_QUERY_EXECUTOR\n\n    return this.#props.plugins !== undefined\n      ? executor.withPlugins(this.#props.plugins)\n      : executor\n  }\n\n  #toOperationNode(executor: QueryExecutor): RawNode {\n    return executor.transformQuery(this.#props.rawNode, this.#props.queryId)\n  }\n\n  #compile(executor: QueryExecutor): CompiledQuery {\n    return executor.compileQuery(\n      this.#toOperationNode(executor),\n      this.#props.queryId,\n    )\n  }\n}\n\nexport interface RawBuilderProps {\n  readonly queryId: QueryId\n  readonly rawNode: RawNode\n  readonly plugins?: ReadonlyArray<KyselyPlugin>\n}\n\nexport function createRawBuilder<O>(props: RawBuilderProps): RawBuilder<O> {\n  return new RawBuilderImpl(props)\n}\n\n/**\n * {@link RawBuilder} with an alias. The result of calling {@link RawBuilder.as}.\n */\nexport interface AliasedRawBuilder<\n  O = unknown,\n  A extends string = never,\n> extends AliasedExpression<O, A> {\n  get rawBuilder(): RawBuilder<O>\n}\n\nclass AliasedRawBuilderImpl<\n  O = unknown,\n  A extends string = never,\n> implements AliasedRawBuilder<O, A> {\n  readonly #rawBuilder: RawBuilder<O>\n  readonly #alias: A | Expression<unknown>\n\n  constructor(rawBuilder: RawBuilder<O>, alias: A | Expression<unknown>) {\n    this.#rawBuilder = rawBuilder\n    this.#alias = alias\n  }\n\n  get expression(): Expression<O> {\n    return this.#rawBuilder\n  }\n\n  get alias(): A | Expression<unknown> {\n    return this.#alias\n  }\n\n  get rawBuilder(): RawBuilder<O> {\n    return this.#rawBuilder\n  }\n\n  toOperationNode(): AliasNode {\n    return AliasNode.create(\n      this.#rawBuilder.toOperationNode(),\n      isOperationNodeSource(this.#alias)\n        ? this.#alias.toOperationNode()\n        : IdentifierNode.create(this.#alias),\n    )\n  }\n}\n"
  },
  {
    "path": "src/raw-builder/sql.ts",
    "content": "import { IdentifierNode } from '../operation-node/identifier-node.js'\nimport { isOperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { OperationNode } from '../operation-node/operation-node.js'\nimport { RawNode } from '../operation-node/raw-node.js'\nimport { ValueNode } from '../operation-node/value-node.js'\nimport { parseStringReference } from '../parser/reference-parser.js'\nimport { parseTable } from '../parser/table-parser.js'\nimport { parseValueExpression } from '../parser/value-parser.js'\nimport { createQueryId } from '../util/query-id.js'\nimport { type RawBuilder, createRawBuilder } from './raw-builder.js'\n\nexport interface Sql {\n  /**\n   * Template tag for creating raw SQL snippets and queries.\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   * import type { Person } from 'type-editor' // imaginary module\n   *\n   * const id = 123\n   * const snippet = sql<Person[]>`select * from person where id = ${id}`\n   * ```\n   *\n   * Substitutions (the things inside `${}`) are automatically passed to the database\n   * as parameters and are never interpolated to the SQL string. There's no need to worry\n   * about SQL injection vulnerabilities. Substitutions can be values, other `sql`\n   * expressions, queries and almost anything else Kysely can produce and they get\n   * handled correctly. See the examples below.\n   *\n   * If you need your substitutions to be interpreted as identifiers, value literals or\n   * lists of things, see the {@link Sql.ref}, {@link Sql.table}, {@link Sql.id},\n   * {@link Sql.lit}, {@link Sql.raw} and {@link Sql.join} functions.\n   *\n   * You can pass sql snippets returned by the `sql` tag pretty much anywhere. Whenever\n   * something can't be done using the Kysely API, you should be able to drop down to\n   * raw SQL using the `sql` tag. Here's an example query that uses raw sql in a bunch\n   * of methods:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const nicknames = ['johnny', 'john', 'jon']\n   * const date1 = new Date('2000-01-01')\n   * const date2 = new Date('2001-01-01')\n   *\n   * const persons = await db\n   *   .selectFrom('person')\n   *   .select(\n   *     // If you use `sql` in a select statement, remember to call the `as`\n   *     // method to give it an alias.\n   *     sql<string>`concat(first_name, ' ', last_name)`.as('full_name')\n   *   )\n   *   .where(sql<boolean>`birthdate between ${date1} and ${date2}`)\n   *   // Here we assume we have list of nicknames for the person\n   *   // (a list of strings) and we use the PostgreSQL `@>` operator\n   *   // to test if all of them are valid nicknames for the user.\n   *   .where('nicknames', '@>', sql<string[]>`ARRAY[${sql.join(nicknames)}]`)\n   *   .orderBy(sql<string>`concat(first_name, ' ', last_name)`)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select concat(first_name, ' ', last_name) as \"full_name\"\n   * from \"person\"\n   * where birthdate between $1 and $2\n   * and \"nicknames\" @> ARRAY[$3, $4, $5, $6, $7, $8, $9, $10]\n   * order by concat(first_name, ' ', last_name)\n   * ```\n   *\n   * SQL snippets can be executed by calling the `execute` method and passing a `Kysely`\n   * instance as the only argument:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   * import type { Person } from 'type-editor'\n   *\n   * const { rows: results } = await sql<Person[]>`select * from person`.execute(db)\n   * ```\n   *\n   * You can merge other `sql` expressions and queries using substitutions:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const petName = db.selectFrom('pet').select('name').limit(1)\n   * const fullName = sql<string>`concat(first_name, ' ', last_name)`\n   *\n   * sql<{ full_name: string; pet_name: string }[]>`\n   *   select ${fullName} as full_name, ${petName} as pet_name\n   *   from person\n   * `.execute(db)\n   * ```\n   *\n   * Substitutions also handle {@link ExpressionBuilder.ref},\n   * {@link DynamicModule.ref} and pretty much anything else you\n   * throw at it. Here's an example of calling a function in a\n   * type-safe way:\n   *\n   * ```ts\n   * db.selectFrom('person')\n   *   .select([\n   *     'first_name',\n   *     'last_name',\n   *     (eb) => {\n   *       // The `eb.ref` method is type-safe and only accepts\n   *       // column references that are possible.\n   *       const firstName = eb.ref('first_name')\n   *       const lastName = eb.ref('last_name')\n   *\n   *       const fullName = sql<string>`concat(${firstName}, ' ', ${lastName})`\n   *       return fullName.as('full_name')\n   *     }\n   *   ])\n   * ```\n   *\n   * don't know if that amount of ceremony is worth the small increase in\n   * type-safety though... But it's possible.\n   */\n  <T = unknown>(\n    sqlFragments: TemplateStringsArray,\n    ...parameters: unknown[]\n  ): RawBuilder<T>\n\n  /**\n   * `sql.val(value)` is a shortcut for:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const value = 123\n   * type ValueType = typeof value\n   *\n   * sql<ValueType>`${value}`\n   * ```\n   */\n  val<V>(value: V): RawBuilder<V>\n\n  /**\n   * @deprecated Use {@link Sql.val} instead.\n   */\n  value<V>(value: V): RawBuilder<V>\n\n  /**\n   * This can be used to add runtime column references to SQL snippets.\n   *\n   * By default `${}` substitutions in {@link sql} template strings get\n   * transformed into parameters. You can use this function to tell\n   * Kysely to interpret them as column references instead.\n   *\n   * WARNING! Using this with unchecked inputs WILL lead to SQL injection\n   * vulnerabilities. The input is not checked or escaped by Kysely in any way.\n   *\n   * ```ts\n   * const columnRef = 'first_name'\n   *\n   * sql`select ${sql.ref(columnRef)} from person`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"first_name\" from person\n   * ```\n   *\n   * The references can also include a table name:\n   *\n   * ```ts\n   * const columnRef = 'person.first_name'\n   *\n   * sql`select ${sql.ref(columnRef)}} from person`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"person\".\"first_name\" from person\n   * ```\n   *\n   * The references can also include a schema on supported databases:\n   *\n   * ```ts\n   * const columnRef = 'public.person.first_name'\n   *\n   * sql`select ${sql.ref(columnRef)}} from person`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"public\".\"person\".\"first_name\" from person\n   * ```\n   */\n  ref<R = unknown>(columnReference: string): RawBuilder<R>\n\n  /**\n   * This can be used to add runtime table references to SQL snippets.\n   *\n   * By default `${}` substitutions in {@link sql} template strings get\n   * transformed into parameters. You can use this function to tell\n   * Kysely to interpret them as table references instead.\n   *\n   * WARNING! Using this with unchecked inputs WILL lead to SQL injection\n   * vulnerabilities. The input is not checked or escaped by Kysely in any way.\n   *\n   * ```ts\n   * const table = 'person'\n   *\n   * sql`select first_name from ${sql.table(table)}`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select first_name from \"person\"\n   * ```\n   *\n   * The references can also include a schema on supported databases:\n   *\n   * ```ts\n   * const table = 'public.person'\n   *\n   * sql`select first_name from ${sql.table(table)}`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select first_name from \"public\".\"person\"\n   * ```\n   */\n  table<T = unknown>(tableReference: string): RawBuilder<T>\n\n  /**\n   * This can be used to add arbitrary identifiers to SQL snippets.\n   *\n   * Does the same thing as {@link Sql.ref | ref} and {@link Sql.table | table}\n   * but can also be used for any other identifiers like index names.\n   *\n   * You should use {@link Sql.ref | ref} and {@link Sql.table | table}\n   * instead of this whenever possible as they produce a more semantic\n   * operation node tree.\n   *\n   * WARNING! Using this with unchecked inputs WILL lead to SQL injection\n   * vulnerabilities. The input is not checked or escaped by Kysely in any way.\n   *\n   * ```ts\n   * const indexName = 'person_first_name_index'\n   *\n   * sql`create index ${indexName} on person`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create index \"person_first_name_index\" on person\n   * ```\n   *\n   * Multiple identifiers get separated by dots:\n   *\n   * ```ts\n   * const schema = 'public'\n   * const columnName = 'first_name'\n   * const table = 'person'\n   *\n   * sql`select ${sql.id(schema, table, columnName)} from ${sql.id(schema, table)}`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select \"public\".\"person\".\"first_name\" from \"public\".\"person\"\n   * ```\n   */\n  id<T = unknown>(...ids: readonly string[]): RawBuilder<T>\n\n  /**\n   * This can be used to add literal values to SQL snippets.\n   *\n   * WARNING! Using this with unchecked inputs WILL lead to SQL injection\n   * vulnerabilities. The input is not checked or escaped by Kysely in any way.\n   * You almost always want to use normal substitutions that get sent to the\n   * db as parameters.\n   *\n   * ```ts\n   * const firstName = 'first_name'\n   *\n   * sql`select * from person where first_name = ${sql.lit(firstName)}`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from person where first_name = 'first_name'\n   * ```\n   *\n   * As you can see from the example above, the value was added directly to\n   * the SQL string instead of as a parameter. Only use this function when\n   * something can't be sent as a parameter.\n   */\n  lit<V>(value: V): RawBuilder<V>\n\n  /**\n   * @deprecated Use {@link lit} instead.\n   */\n  literal<V>(value: V): RawBuilder<V>\n\n  /**\n   * This can be used to add arbitrary runtime SQL to SQL snippets.\n   *\n   * WARNING! Using this with unchecked inputs WILL lead to SQL injection\n   * vulnerabilities. The input is not checked or escaped by Kysely in any way.\n   *\n   * ```ts\n   * const firstName = \"'first_name'\"\n   *\n   * sql`select * from person where first_name = ${sql.raw(firstName)}`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from person where first_name = 'first_name'\n   * ```\n   *\n   * Note that the difference to `sql.lit` is that this function\n   * doesn't assume the inputs are values. The input to this function\n   * can be any sql and it's simply glued to the parent string as-is.\n   */\n  raw<R = unknown>(anySql: string): RawBuilder<R>\n\n  /**\n   * This can be used to add lists of things to SQL snippets.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import type { Person } from 'type-editor' // imaginary module\n   *\n   * function findByNicknames(nicknames: string[]): Promise<Person[]> {\n   *   return db\n   *     .selectFrom('person')\n   *     .selectAll()\n   *     .where('nicknames', '@>', sql<string[]>`ARRAY[${sql.join(nicknames)}]`)\n   *     .execute()\n   * }\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * select * from \"person\"\n   * where \"nicknames\" @> ARRAY[$1, $2, $3, $4, $5, $6, $7, $8]\n   * ```\n   *\n   * The second argument is the joining SQL expression that defaults\n   * to\n   *\n   * ```ts\n   * sql`, `\n   * ```\n   *\n   * In addition to values, items in the list can be also {@link sql}\n   * expressions, queries or anything else the normal substitutions\n   * support:\n   *\n   * ```ts\n   * const things = [\n   *   123,\n   *   sql`(1 == 1)`,\n   *   db.selectFrom('person').selectAll(),\n   *   sql.lit(false),\n   *   sql.id('first_name')\n   * ]\n   *\n   * sql`BEFORE ${sql.join(things, sql`::varchar, `)} AFTER`\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * BEFORE $1::varchar, (1 == 1)::varchar, (select * from \"person\")::varchar, false::varchar, \"first_name\" AFTER\n   * ```\n   */\n  join<T = unknown>(\n    array: readonly unknown[],\n    separator?: RawBuilder<any>,\n  ): RawBuilder<T>\n}\n\nexport const sql: Sql = Object.assign(\n  <T = unknown>(\n    sqlFragments: TemplateStringsArray,\n    ...parameters: unknown[]\n  ): RawBuilder<T> => {\n    return createRawBuilder({\n      queryId: createQueryId(),\n      rawNode: RawNode.create(\n        sqlFragments,\n        parameters?.map(parseParameter) ?? [],\n      ),\n    })\n  },\n  {\n    ref<R = unknown>(columnReference: string): RawBuilder<R> {\n      return createRawBuilder({\n        queryId: createQueryId(),\n        rawNode: RawNode.createWithChild(parseStringReference(columnReference)),\n      })\n    },\n\n    val<V>(value: V): RawBuilder<V> {\n      return createRawBuilder({\n        queryId: createQueryId(),\n        rawNode: RawNode.createWithChild(parseValueExpression(value)),\n      })\n    },\n\n    value<V>(value: V): RawBuilder<V> {\n      return this.val(value)\n    },\n\n    table<T = unknown>(tableReference: string): RawBuilder<T> {\n      return createRawBuilder({\n        queryId: createQueryId(),\n        rawNode: RawNode.createWithChild(parseTable(tableReference)),\n      })\n    },\n\n    id<T = unknown>(...ids: readonly string[]): RawBuilder<T> {\n      const fragments = new Array<string>(ids.length + 1).fill('.')\n\n      fragments[0] = ''\n      fragments[fragments.length - 1] = ''\n\n      return createRawBuilder({\n        queryId: createQueryId(),\n        rawNode: RawNode.create(fragments, ids.map(IdentifierNode.create)),\n      })\n    },\n\n    lit<V>(value: V): RawBuilder<V> {\n      return createRawBuilder({\n        queryId: createQueryId(),\n        rawNode: RawNode.createWithChild(ValueNode.createImmediate(value)),\n      })\n    },\n\n    literal<V>(value: V): RawBuilder<V> {\n      return this.lit(value)\n    },\n\n    raw<R = unknown>(sql: string): RawBuilder<R> {\n      return createRawBuilder({\n        queryId: createQueryId(),\n        rawNode: RawNode.createWithSql(sql),\n      })\n    },\n\n    join<T = unknown>(\n      array: readonly unknown[],\n      separator: RawBuilder<any> = sql`, `,\n    ): RawBuilder<T> {\n      const nodes = new Array<OperationNode>(Math.max(2 * array.length - 1, 0))\n      const sep = separator.toOperationNode()\n\n      for (let i = 0; i < array.length; ++i) {\n        nodes[2 * i] = parseParameter(array[i])\n\n        if (i !== array.length - 1) {\n          nodes[2 * i + 1] = sep\n        }\n      }\n\n      return createRawBuilder({\n        queryId: createQueryId(),\n        rawNode: RawNode.createWithChildren(nodes),\n      })\n    },\n  },\n)\n\nfunction parseParameter(param: unknown): OperationNode {\n  if (isOperationNodeSource(param)) {\n    return param.toOperationNode()\n  }\n\n  return parseValueExpression(param)\n}\n"
  },
  {
    "path": "src/schema/alter-column-builder.ts",
    "content": "import { AlterColumnNode } from '../operation-node/alter-column-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport {\n  type DataTypeExpression,\n  parseDataTypeExpression,\n} from '../parser/data-type-parser.js'\nimport {\n  type DefaultValueExpression,\n  parseDefaultValueExpression,\n} from '../parser/default-value-parser.js'\n\nexport class AlterColumnBuilder {\n  readonly #column: string\n\n  constructor(column: string) {\n    this.#column = column\n  }\n\n  setDataType(dataType: DataTypeExpression): AlteredColumnBuilder {\n    return new AlteredColumnBuilder(\n      AlterColumnNode.create(\n        this.#column,\n        'dataType',\n        parseDataTypeExpression(dataType),\n      ),\n    )\n  }\n\n  setDefault(value: DefaultValueExpression): AlteredColumnBuilder {\n    return new AlteredColumnBuilder(\n      AlterColumnNode.create(\n        this.#column,\n        'setDefault',\n        parseDefaultValueExpression(value),\n      ),\n    )\n  }\n\n  dropDefault(): AlteredColumnBuilder {\n    return new AlteredColumnBuilder(\n      AlterColumnNode.create(this.#column, 'dropDefault', true),\n    )\n  }\n\n  setNotNull(): AlteredColumnBuilder {\n    return new AlteredColumnBuilder(\n      AlterColumnNode.create(this.#column, 'setNotNull', true),\n    )\n  }\n\n  dropNotNull(): AlteredColumnBuilder {\n    return new AlteredColumnBuilder(\n      AlterColumnNode.create(this.#column, 'dropNotNull', true),\n    )\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n}\n\n/**\n * Allows us to force consumers to do exactly one alteration to a column.\n *\n * One cannot do no alterations:\n *\n * ```ts\n * await db.schema\n *   .alterTable('person')\n * //  .execute() // Property 'execute' does not exist on type 'AlteredColumnBuilder'.\n * ```\n *\n * ```ts\n * await db.schema\n *   .alterTable('person')\n * //  .alterColumn('age', (ac) => ac) // Type 'AlterColumnBuilder' is not assignable to type 'AlteredColumnBuilder'.\n * //  .execute()\n * ```\n *\n * One cannot do multiple alterations:\n *\n * ```ts\n * await db.schema\n *   .alterTable('person')\n * //  .alterColumn('age', (ac) => ac.dropNotNull().setNotNull()) // Property 'setNotNull' does not exist on type 'AlteredColumnBuilder'.\n * //  .execute()\n * ```\n *\n * Which would now throw a compilation error, instead of a runtime error.\n */\nexport class AlteredColumnBuilder implements OperationNodeSource {\n  readonly #alterColumnNode: AlterColumnNode\n\n  constructor(alterColumnNode: AlterColumnNode) {\n    this.#alterColumnNode = alterColumnNode\n  }\n\n  toOperationNode(): AlterColumnNode {\n    return this.#alterColumnNode\n  }\n}\n\nexport type AlterColumnBuilderCallback = (\n  builder: AlterColumnBuilder,\n) => AlteredColumnBuilder\n"
  },
  {
    "path": "src/schema/alter-table-add-foreign-key-constraint-builder.ts",
    "content": "import { AddConstraintNode } from '../operation-node/add-constraint-node.js'\nimport { AlterTableNode } from '../operation-node/alter-table-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { OnModifyForeignAction } from '../operation-node/references-node.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { Compilable } from '../util/compilable.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { QueryId } from '../util/query-id.js'\nimport type {\n  ForeignKeyConstraintBuilder,\n  ForeignKeyConstraintBuilderInterface,\n} from './foreign-key-constraint-builder.js'\n\nexport class AlterTableAddForeignKeyConstraintBuilder\n  implements\n    ForeignKeyConstraintBuilderInterface<AlterTableAddForeignKeyConstraintBuilder>,\n    OperationNodeSource,\n    Compilable\n{\n  readonly #props: AlterTableAddForeignKeyConstraintBuilderProps\n\n  constructor(props: AlterTableAddForeignKeyConstraintBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  onDelete(\n    onDelete: OnModifyForeignAction,\n  ): AlterTableAddForeignKeyConstraintBuilder {\n    return new AlterTableAddForeignKeyConstraintBuilder({\n      ...this.#props,\n      constraintBuilder: this.#props.constraintBuilder.onDelete(onDelete),\n    })\n  }\n\n  onUpdate(\n    onUpdate: OnModifyForeignAction,\n  ): AlterTableAddForeignKeyConstraintBuilder {\n    return new AlterTableAddForeignKeyConstraintBuilder({\n      ...this.#props,\n      constraintBuilder: this.#props.constraintBuilder.onUpdate(onUpdate),\n    })\n  }\n\n  deferrable(): AlterTableAddForeignKeyConstraintBuilder {\n    return new AlterTableAddForeignKeyConstraintBuilder({\n      ...this.#props,\n      constraintBuilder: this.#props.constraintBuilder.deferrable(),\n    })\n  }\n\n  notDeferrable(): AlterTableAddForeignKeyConstraintBuilder {\n    return new AlterTableAddForeignKeyConstraintBuilder({\n      ...this.#props,\n      constraintBuilder: this.#props.constraintBuilder.notDeferrable(),\n    })\n  }\n\n  initiallyDeferred(): AlterTableAddForeignKeyConstraintBuilder {\n    return new AlterTableAddForeignKeyConstraintBuilder({\n      ...this.#props,\n      constraintBuilder: this.#props.constraintBuilder.initiallyDeferred(),\n    })\n  }\n\n  initiallyImmediate(): AlterTableAddForeignKeyConstraintBuilder {\n    return new AlterTableAddForeignKeyConstraintBuilder({\n      ...this.#props,\n      constraintBuilder: this.#props.constraintBuilder.initiallyImmediate(),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): AlterTableNode {\n    return this.#props.executor.transformQuery(\n      AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addConstraint: AddConstraintNode.create(\n          this.#props.constraintBuilder.toOperationNode(),\n        ),\n      }),\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface AlterTableAddForeignKeyConstraintBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: AlterTableNode\n  readonly constraintBuilder: ForeignKeyConstraintBuilder\n}\n"
  },
  {
    "path": "src/schema/alter-table-add-index-builder.ts",
    "content": "import type { Expression } from '../expression/expression.js'\nimport { AddIndexNode } from '../operation-node/add-index-node.js'\nimport { AlterTableNode } from '../operation-node/alter-table-node.js'\nimport type { IndexType } from '../operation-node/create-index-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { RawNode } from '../operation-node/raw-node.js'\nimport {\n  type OrderedColumnName,\n  parseOrderedColumnName,\n} from '../parser/reference-parser.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { Compilable } from '../util/compilable.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { QueryId } from '../util/query-id.js'\n\nexport class AlterTableAddIndexBuilder\n  implements OperationNodeSource, Compilable\n{\n  readonly #props: AlterTableAddIndexBuilderProps\n\n  constructor(props: AlterTableAddIndexBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Makes the index unique.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .alterTable('person')\n   *   .addIndex('person_first_name_index')\n   *   .unique()\n   *   .column('email')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * alter table `person` add unique index `person_first_name_index` (`email`)\n   * ```\n   */\n  unique(): AlterTableAddIndexBuilder {\n    return new AlterTableAddIndexBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addIndex: AddIndexNode.cloneWith(this.#props.node.addIndex!, {\n          unique: true,\n        }),\n      }),\n    })\n  }\n\n  /**\n   * Adds a column to the index.\n   *\n   * Also see {@link columns} for adding multiple columns at once or {@link expression}\n   * for specifying an arbitrary expression.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .alterTable('person')\n   *   .addIndex('person_first_name_and_age_index')\n   *   .column('first_name')\n   *   .column('age desc')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * alter table `person` add index `person_first_name_and_age_index` (`first_name`, `age` desc)\n   * ```\n   */\n  column<CL extends string>(\n    column: OrderedColumnName<CL>,\n  ): AlterTableAddIndexBuilder {\n    return new AlterTableAddIndexBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addIndex: AddIndexNode.cloneWithColumns(this.#props.node.addIndex!, [\n          parseOrderedColumnName(column),\n        ]),\n      }),\n    })\n  }\n\n  /**\n   * Specifies a list of columns for the index.\n   *\n   * Also see {@link column} for adding a single column or {@link expression} for\n   * specifying an arbitrary expression.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .alterTable('person')\n   *   .addIndex('person_first_name_and_age_index')\n   *   .columns(['first_name', 'age desc'])\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * alter table `person` add index `person_first_name_and_age_index` (`first_name`, `age` desc)\n   * ```\n   */\n  columns<CL extends string>(\n    columns: OrderedColumnName<CL>[],\n  ): AlterTableAddIndexBuilder {\n    return new AlterTableAddIndexBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addIndex: AddIndexNode.cloneWithColumns(\n          this.#props.node.addIndex!,\n          columns.map(parseOrderedColumnName),\n        ),\n      }),\n    })\n  }\n\n  /**\n   * Specifies an arbitrary expression for the index.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .alterTable('person')\n   *   .addIndex('person_first_name_index')\n   *   .expression(sql<boolean>`(first_name < 'Sami')`)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * alter table `person` add index `person_first_name_index` ((first_name < 'Sami'))\n   * ```\n   */\n  expression(expression: Expression<any>): AlterTableAddIndexBuilder {\n    return new AlterTableAddIndexBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addIndex: AddIndexNode.cloneWithColumns(this.#props.node.addIndex!, [\n          expression.toOperationNode(),\n        ]),\n      }),\n    })\n  }\n\n  /**\n   * Specifies the index type.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .alterTable('person')\n   *   .addIndex('person_first_name_index')\n   *   .column('first_name')\n   *   .using('hash')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * alter table `person` add index `person_first_name_index` (`first_name`) using hash\n   * ```\n   */\n  using(indexType: IndexType): AlterTableAddIndexBuilder\n  using(indexType: string): AlterTableAddIndexBuilder\n  using(indexType: string): AlterTableAddIndexBuilder {\n    return new AlterTableAddIndexBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addIndex: AddIndexNode.cloneWith(this.#props.node.addIndex!, {\n          using: RawNode.createWithSql(indexType),\n        }),\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): AlterTableNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface AlterTableAddIndexBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: AlterTableNode\n}\n"
  },
  {
    "path": "src/schema/alter-table-builder.ts",
    "content": "import { AddColumnNode } from '../operation-node/add-column-node.js'\nimport { AlterTableNode } from '../operation-node/alter-table-node.js'\nimport { ColumnDefinitionNode } from '../operation-node/column-definition-node.js'\nimport { DropColumnNode } from '../operation-node/drop-column-node.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { RenameColumnNode } from '../operation-node/rename-column-node.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport { freeze, noop } from '../util/object-utils.js'\nimport {\n  ColumnDefinitionBuilder,\n  type ColumnDefinitionBuilderCallback,\n} from './column-definition-builder.js'\nimport type { QueryId } from '../util/query-id.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport { ModifyColumnNode } from '../operation-node/modify-column-node.js'\nimport {\n  type DataTypeExpression,\n  parseDataTypeExpression,\n} from '../parser/data-type-parser.js'\nimport {\n  ForeignKeyConstraintBuilder,\n  type ForeignKeyConstraintBuilderCallback,\n} from './foreign-key-constraint-builder.js'\nimport { AddConstraintNode } from '../operation-node/add-constraint-node.js'\nimport { UniqueConstraintNode } from '../operation-node/unique-constraint-node.js'\nimport { CheckConstraintNode } from '../operation-node/check-constraint-node.js'\nimport { ForeignKeyConstraintNode } from '../operation-node/foreign-key-constraint-node.js'\nimport { ColumnNode } from '../operation-node/column-node.js'\nimport { parseTable } from '../parser/table-parser.js'\nimport { DropConstraintNode } from '../operation-node/drop-constraint-node.js'\nimport type { Expression } from '../expression/expression.js'\nimport {\n  AlterColumnBuilder,\n  type AlterColumnBuilderCallback,\n} from './alter-column-builder.js'\nimport { AlterTableExecutor } from './alter-table-executor.js'\nimport { AlterTableAddForeignKeyConstraintBuilder } from './alter-table-add-foreign-key-constraint-builder.js'\nimport { AlterTableDropConstraintBuilder } from './alter-table-drop-constraint-builder.js'\nimport { PrimaryKeyConstraintNode } from '../operation-node/primary-key-constraint-node.js'\nimport { DropIndexNode } from '../operation-node/drop-index-node.js'\nimport { AddIndexNode } from '../operation-node/add-index-node.js'\nimport { AlterTableAddIndexBuilder } from './alter-table-add-index-builder.js'\nimport {\n  UniqueConstraintNodeBuilder,\n  type UniqueConstraintNodeBuilderCallback,\n} from './unique-constraint-builder.js'\nimport {\n  PrimaryKeyConstraintBuilder,\n  type PrimaryKeyConstraintBuilderCallback,\n} from './primary-key-constraint-builder.js'\nimport {\n  CheckConstraintBuilder,\n  type CheckConstraintBuilderCallback,\n} from './check-constraint-builder.js'\nimport { RenameConstraintNode } from '../operation-node/rename-constraint-node.js'\n\n/**\n * This builder can be used to create a `alter table` query.\n */\nexport class AlterTableBuilder implements ColumnAlteringInterface {\n  readonly #props: AlterTableBuilderProps\n\n  constructor(props: AlterTableBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  renameTo(newTableName: string): AlterTableExecutor {\n    return new AlterTableExecutor({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        renameTo: parseTable(newTableName),\n      }),\n    })\n  }\n\n  setSchema(newSchema: string): AlterTableExecutor {\n    return new AlterTableExecutor({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        setSchema: IdentifierNode.create(newSchema),\n      }),\n    })\n  }\n\n  alterColumn(\n    column: string,\n    alteration: AlterColumnBuilderCallback,\n  ): AlterTableColumnAlteringBuilder {\n    const builder = alteration(new AlterColumnBuilder(column))\n\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        builder.toOperationNode(),\n      ),\n    })\n  }\n\n  dropColumn(column: string): AlterTableColumnAlteringBuilder {\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        DropColumnNode.create(column),\n      ),\n    })\n  }\n\n  renameColumn(\n    column: string,\n    newColumn: string,\n  ): AlterTableColumnAlteringBuilder {\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        RenameColumnNode.create(column, newColumn),\n      ),\n    })\n  }\n\n  addColumn(\n    columnName: string,\n    dataType: DataTypeExpression,\n    build: ColumnDefinitionBuilderCallback = noop,\n  ): AlterTableColumnAlteringBuilder {\n    const builder = build(\n      new ColumnDefinitionBuilder(\n        ColumnDefinitionNode.create(\n          columnName,\n          parseDataTypeExpression(dataType),\n        ),\n      ),\n    )\n\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        AddColumnNode.create(builder.toOperationNode()),\n      ),\n    })\n  }\n\n  modifyColumn(\n    columnName: string,\n    dataType: DataTypeExpression,\n    build: ColumnDefinitionBuilderCallback = noop,\n  ): AlterTableColumnAlteringBuilder {\n    const builder = build(\n      new ColumnDefinitionBuilder(\n        ColumnDefinitionNode.create(\n          columnName,\n          parseDataTypeExpression(dataType),\n        ),\n      ),\n    )\n\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        ModifyColumnNode.create(builder.toOperationNode()),\n      ),\n    })\n  }\n\n  /**\n   * See {@link CreateTableBuilder.addUniqueConstraint}\n   */\n  addUniqueConstraint(\n    constraintName: string,\n    columns: string[],\n    build: UniqueConstraintNodeBuilderCallback = noop,\n  ): AlterTableExecutor {\n    const uniqueConstraintBuilder = build(\n      new UniqueConstraintNodeBuilder(\n        UniqueConstraintNode.create(columns, constraintName),\n      ),\n    )\n\n    return new AlterTableExecutor({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addConstraint: AddConstraintNode.create(\n          uniqueConstraintBuilder.toOperationNode(),\n        ),\n      }),\n    })\n  }\n\n  /**\n   * See {@link CreateTableBuilder.addCheckConstraint}\n   */\n  addCheckConstraint(\n    constraintName: string,\n    checkExpression: Expression<any>,\n    build: CheckConstraintBuilderCallback = noop,\n  ): AlterTableExecutor {\n    const constraintBuilder = build(\n      new CheckConstraintBuilder(\n        CheckConstraintNode.create(\n          checkExpression.toOperationNode(),\n          constraintName,\n        ),\n      ),\n    )\n\n    return new AlterTableExecutor({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addConstraint: AddConstraintNode.create(\n          constraintBuilder.toOperationNode(),\n        ),\n      }),\n    })\n  }\n\n  /**\n   * See {@link CreateTableBuilder.addForeignKeyConstraint}\n   *\n   * Unlike {@link CreateTableBuilder.addForeignKeyConstraint} this method returns\n   * the constraint builder and doesn't take a callback as the last argument. This\n   * is because you can only add one column per `ALTER TABLE` query.\n   */\n  addForeignKeyConstraint(\n    constraintName: string,\n    columns: string[],\n    targetTable: string,\n    targetColumns: string[],\n    build: ForeignKeyConstraintBuilderCallback = noop,\n  ): AlterTableAddForeignKeyConstraintBuilder {\n    const constraintBuilder = build(\n      new ForeignKeyConstraintBuilder(\n        ForeignKeyConstraintNode.create(\n          columns.map(ColumnNode.create),\n          parseTable(targetTable),\n          targetColumns.map(ColumnNode.create),\n          constraintName,\n        ),\n      ),\n    )\n\n    return new AlterTableAddForeignKeyConstraintBuilder({\n      ...this.#props,\n      constraintBuilder,\n    })\n  }\n\n  /**\n   * See {@link CreateTableBuilder.addPrimaryKeyConstraint}\n   */\n  addPrimaryKeyConstraint(\n    constraintName: string,\n    columns: string[],\n    build: PrimaryKeyConstraintBuilderCallback = noop,\n  ): AlterTableExecutor {\n    const constraintBuilder = build(\n      new PrimaryKeyConstraintBuilder(\n        PrimaryKeyConstraintNode.create(columns, constraintName),\n      ),\n    )\n\n    return new AlterTableExecutor({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addConstraint: AddConstraintNode.create(\n          constraintBuilder.toOperationNode(),\n        ),\n      }),\n    })\n  }\n\n  dropConstraint(constraintName: string): AlterTableDropConstraintBuilder {\n    return new AlterTableDropConstraintBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        dropConstraint: DropConstraintNode.create(constraintName),\n      }),\n    })\n  }\n\n  renameConstraint(\n    oldName: string,\n    newName: string,\n  ): AlterTableDropConstraintBuilder {\n    return new AlterTableDropConstraintBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        renameConstraint: RenameConstraintNode.create(oldName, newName),\n      }),\n    })\n  }\n\n  /**\n   * This can be used to add index to table.\n   *\n   *  ### Examples\n   *\n   * ```ts\n   * db.schema.alterTable('person')\n   *   .addIndex('person_email_index')\n   *   .column('email')\n   *   .unique()\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * alter table `person` add unique index `person_email_index` (`email`)\n   * ```\n   */\n  addIndex(indexName: string): AlterTableAddIndexBuilder {\n    return new AlterTableAddIndexBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        addIndex: AddIndexNode.create(indexName),\n      }),\n    })\n  }\n\n  /**\n   * This can be used to drop index from table.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * db.schema.alterTable('person')\n   *   .dropIndex('person_email_index')\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * alter table `person` drop index `test_first_name_index`\n   * ```\n   */\n  dropIndex(indexName: string): AlterTableExecutor {\n    return new AlterTableExecutor({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        dropIndex: DropIndexNode.create(indexName),\n      }),\n    })\n  }\n\n  /**\n   * Calls the given function passing `this` as the only argument.\n   *\n   * See {@link CreateTableBuilder.$call}\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n}\n\nexport interface AlterTableBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: AlterTableNode\n}\n\nexport interface ColumnAlteringInterface {\n  alterColumn(\n    column: string,\n    alteration: AlterColumnBuilderCallback,\n  ): ColumnAlteringInterface\n\n  dropColumn(column: string): ColumnAlteringInterface\n\n  renameColumn(column: string, newColumn: string): ColumnAlteringInterface\n\n  /**\n   * See {@link CreateTableBuilder.addColumn}\n   */\n  addColumn(\n    columnName: string,\n    dataType: DataTypeExpression,\n    build?: ColumnDefinitionBuilderCallback,\n  ): ColumnAlteringInterface\n\n  /**\n   * Creates an `alter table modify column` query. The `modify column` statement\n   * is only implemeted by MySQL and oracle AFAIK. On other databases you\n   * should use the `alterColumn` method.\n   */\n  modifyColumn(\n    columnName: string,\n    dataType: DataTypeExpression,\n    build: ColumnDefinitionBuilderCallback,\n  ): ColumnAlteringInterface\n}\n\nexport class AlterTableColumnAlteringBuilder\n  implements ColumnAlteringInterface, OperationNodeSource, Compilable\n{\n  readonly #props: AlterTableColumnAlteringBuilderProps\n\n  constructor(props: AlterTableColumnAlteringBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  alterColumn(\n    column: string,\n    alteration: AlterColumnBuilderCallback,\n  ): AlterTableColumnAlteringBuilder {\n    const builder = alteration(new AlterColumnBuilder(column))\n\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        builder.toOperationNode(),\n      ),\n    })\n  }\n\n  dropColumn(column: string): AlterTableColumnAlteringBuilder {\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        DropColumnNode.create(column),\n      ),\n    })\n  }\n\n  renameColumn(\n    column: string,\n    newColumn: string,\n  ): AlterTableColumnAlteringBuilder {\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        RenameColumnNode.create(column, newColumn),\n      ),\n    })\n  }\n\n  addColumn(\n    columnName: string,\n    dataType: DataTypeExpression,\n    build: ColumnDefinitionBuilderCallback = noop,\n  ): AlterTableColumnAlteringBuilder {\n    const builder = build(\n      new ColumnDefinitionBuilder(\n        ColumnDefinitionNode.create(\n          columnName,\n          parseDataTypeExpression(dataType),\n        ),\n      ),\n    )\n\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        AddColumnNode.create(builder.toOperationNode()),\n      ),\n    })\n  }\n\n  modifyColumn(\n    columnName: string,\n    dataType: DataTypeExpression,\n    build: ColumnDefinitionBuilderCallback = noop,\n  ): AlterTableColumnAlteringBuilder {\n    const builder = build(\n      new ColumnDefinitionBuilder(\n        ColumnDefinitionNode.create(\n          columnName,\n          parseDataTypeExpression(dataType),\n        ),\n      ),\n    )\n\n    return new AlterTableColumnAlteringBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithColumnAlteration(\n        this.#props.node,\n        ModifyColumnNode.create(builder.toOperationNode()),\n      ),\n    })\n  }\n\n  toOperationNode(): AlterTableNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface AlterTableColumnAlteringBuilderProps extends AlterTableBuilderProps {}\n"
  },
  {
    "path": "src/schema/alter-table-drop-constraint-builder.ts",
    "content": "import { AlterTableNode } from '../operation-node/alter-table-node.js'\nimport { DropConstraintNode } from '../operation-node/drop-constraint-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { Compilable } from '../util/compilable.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { QueryId } from '../util/query-id.js'\n\nexport class AlterTableDropConstraintBuilder\n  implements OperationNodeSource, Compilable\n{\n  readonly #props: AlterTableDropConstraintBuilderProps\n\n  constructor(props: AlterTableDropConstraintBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  ifExists(): AlterTableDropConstraintBuilder {\n    return new AlterTableDropConstraintBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        dropConstraint: DropConstraintNode.cloneWith(\n          this.#props.node.dropConstraint!,\n          {\n            ifExists: true,\n          },\n        ),\n      }),\n    })\n  }\n\n  cascade(): AlterTableDropConstraintBuilder {\n    return new AlterTableDropConstraintBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        dropConstraint: DropConstraintNode.cloneWith(\n          this.#props.node.dropConstraint!,\n          {\n            modifier: 'cascade',\n          },\n        ),\n      }),\n    })\n  }\n\n  restrict(): AlterTableDropConstraintBuilder {\n    return new AlterTableDropConstraintBuilder({\n      ...this.#props,\n      node: AlterTableNode.cloneWithTableProps(this.#props.node, {\n        dropConstraint: DropConstraintNode.cloneWith(\n          this.#props.node.dropConstraint!,\n          {\n            modifier: 'restrict',\n          },\n        ),\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): AlterTableNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface AlterTableDropConstraintBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: AlterTableNode\n}\n"
  },
  {
    "path": "src/schema/alter-table-executor.ts",
    "content": "import type { AlterTableNode } from '../operation-node/alter-table-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { Compilable } from '../util/compilable.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { QueryId } from '../util/query-id.js'\n\nexport class AlterTableExecutor implements OperationNodeSource, Compilable {\n  readonly #props: AlterTableExecutorProps\n\n  constructor(props: AlterTableExecutorProps) {\n    this.#props = freeze(props)\n  }\n\n  toOperationNode(): AlterTableNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface AlterTableExecutorProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: AlterTableNode\n}\n"
  },
  {
    "path": "src/schema/check-constraint-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CheckConstraintNode } from '../operation-node/check-constraint-node.js'\n\nexport class CheckConstraintBuilder implements OperationNodeSource {\n  readonly #node: CheckConstraintNode\n\n  constructor(node: CheckConstraintNode) {\n    this.#node = node\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): CheckConstraintNode {\n    return this.#node\n  }\n}\n\nexport type CheckConstraintBuilderCallback = (\n  builder: CheckConstraintBuilder,\n) => CheckConstraintBuilder\n"
  },
  {
    "path": "src/schema/column-definition-builder.ts",
    "content": "import { CheckConstraintNode } from '../operation-node/check-constraint-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport {\n  type OnModifyForeignAction,\n  ReferencesNode,\n} from '../operation-node/references-node.js'\nimport { SelectAllNode } from '../operation-node/select-all-node.js'\nimport { parseStringReference } from '../parser/reference-parser.js'\nimport { ColumnDefinitionNode } from '../operation-node/column-definition-node.js'\nimport {\n  type DefaultValueExpression,\n  parseDefaultValueExpression,\n} from '../parser/default-value-parser.js'\nimport { GeneratedNode } from '../operation-node/generated-node.js'\nimport { DefaultValueNode } from '../operation-node/default-value-node.js'\nimport { parseOnModifyForeignAction } from '../parser/on-modify-action-parser.js'\nimport type { Expression } from '../expression/expression.js'\n\nexport class ColumnDefinitionBuilder implements OperationNodeSource {\n  readonly #node: ColumnDefinitionNode\n\n  constructor(node: ColumnDefinitionNode) {\n    this.#node = node\n  }\n\n  /**\n   * Adds `auto_increment` or `autoincrement` to the column definition\n   * depending on the dialect.\n   *\n   * Some dialects like PostgreSQL don't support this. On PostgreSQL\n   * you can use the `serial` or `bigserial` data type instead.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.autoIncrement().primaryKey())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `id` integer primary key auto_increment\n   * )\n   * ```\n   */\n  autoIncrement(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, { autoIncrement: true }),\n    )\n  }\n\n  /**\n   * Makes the column an identity column.\n   *\n   * This only works on some dialects like MS SQL Server (MSSQL).\n   *\n   * For PostgreSQL's `generated always as identity` use {@link generatedAlwaysAsIdentity}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.identity().primaryKey())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MSSQL):\n   *\n   * ```sql\n   * create table \"person\" (\n   *   \"id\" integer identity primary key\n   * )\n   * ```\n   */\n  identity(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, { identity: true }),\n    )\n  }\n\n  /**\n   * Makes the column the primary key.\n   *\n   * If you want to specify a composite primary key use the\n   * {@link CreateTableBuilder.addPrimaryKeyConstraint} method.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.primaryKey())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `id` integer primary key\n   * )\n   */\n  primaryKey(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, { primaryKey: true }),\n    )\n  }\n\n  /**\n   * Adds a foreign key constraint for the column.\n   *\n   * If your database engine doesn't support foreign key constraints in the\n   * column definition (like MySQL 5) you need to call the table level\n   * {@link CreateTableBuilder.addForeignKeyConstraint} method instead.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn('owner_id', 'integer', (col) => col.references('person.id'))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create table \"pet\" (\n   *   \"owner_id\" integer references \"person\" (\"id\")\n   * )\n   * ```\n   */\n  references(ref: string): ColumnDefinitionBuilder {\n    const references = parseStringReference(ref)\n\n    if (!references.table || SelectAllNode.is(references.column)) {\n      throw new Error(\n        `invalid call references('${ref}'). The reference must have format table.column or schema.table.column`,\n      )\n    }\n\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, {\n        references: ReferencesNode.create(references.table, [\n          references.column,\n        ]),\n      }),\n    )\n  }\n\n  /**\n   * Adds an `on delete` constraint for the foreign key column.\n   *\n   * If your database engine doesn't support foreign key constraints in the\n   * column definition (like MySQL 5) you need to call the table level\n   * {@link CreateTableBuilder.addForeignKeyConstraint} method instead.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn(\n   *     'owner_id',\n   *     'integer',\n   *     (col) => col.references('person.id').onDelete('cascade')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create table \"pet\" (\n   *   \"owner_id\" integer references \"person\" (\"id\") on delete cascade\n   * )\n   * ```\n   */\n  onDelete(onDelete: OnModifyForeignAction): ColumnDefinitionBuilder {\n    if (!this.#node.references) {\n      throw new Error('on delete constraint can only be added for foreign keys')\n    }\n\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, {\n        references: ReferencesNode.cloneWithOnDelete(\n          this.#node.references,\n          parseOnModifyForeignAction(onDelete),\n        ),\n      }),\n    )\n  }\n\n  /**\n   * Adds an `on update` constraint for the foreign key column.\n   *\n   * If your database engine doesn't support foreign key constraints in the\n   * column definition (like MySQL 5) you need to call the table level\n   * {@link CreateTableBuilder.addForeignKeyConstraint} method instead.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn(\n   *     'owner_id',\n   *     'integer',\n   *     (col) => col.references('person.id').onUpdate('cascade')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create table \"pet\" (\n   *   \"owner_id\" integer references \"person\" (\"id\") on update cascade\n   * )\n   * ```\n   */\n  onUpdate(onUpdate: OnModifyForeignAction): ColumnDefinitionBuilder {\n    if (!this.#node.references) {\n      throw new Error('on update constraint can only be added for foreign keys')\n    }\n\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, {\n        references: ReferencesNode.cloneWithOnUpdate(\n          this.#node.references,\n          parseOnModifyForeignAction(onUpdate),\n        ),\n      }),\n    )\n  }\n\n  /**\n   * Adds a unique constraint for the column.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('email', 'varchar(255)', col => col.unique())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `email` varchar(255) unique\n   * )\n   * ```\n   */\n  unique(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, { unique: true }),\n    )\n  }\n\n  /**\n   * Adds a `not null` constraint for the column.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('first_name', 'varchar(255)', col => col.notNull())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `first_name` varchar(255) not null\n   * )\n   * ```\n   */\n  notNull(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, { notNull: true }),\n    )\n  }\n\n  /**\n   * Adds a `unsigned` modifier for the column.\n   *\n   * This only works on some dialects like MySQL.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('age', 'integer', col => col.unsigned())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `age` integer unsigned\n   * )\n   * ```\n   */\n  unsigned(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, { unsigned: true }),\n    )\n  }\n\n  /**\n   * Adds a default value constraint for the column.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn('number_of_legs', 'integer', (col) => col.defaultTo(4))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `pet` (\n   *   `number_of_legs` integer default 4\n   * )\n   * ```\n   *\n   * Values passed to `defaultTo` are interpreted as value literals by default. You can define\n   * an arbitrary SQL expression using the {@link sql} template tag:\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn(\n   *     'created_at',\n   *     'timestamp',\n   *     (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `pet` (\n   *   `created_at` timestamp default CURRENT_TIMESTAMP\n   * )\n   * ```\n   */\n  defaultTo(value: DefaultValueExpression): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, {\n        defaultTo: DefaultValueNode.create(parseDefaultValueExpression(value)),\n      }),\n    )\n  }\n\n  /**\n   * Adds a check constraint for the column.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn('number_of_legs', 'integer', (col) =>\n   *     col.check(sql`number_of_legs < 5`)\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `pet` (\n   *   `number_of_legs` integer check (number_of_legs < 5)\n   * )\n   * ```\n   */\n  check(expression: Expression<any>): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, {\n        check: CheckConstraintNode.create(expression.toOperationNode()),\n      }),\n    )\n  }\n\n  /**\n   * Makes the column a generated column using a `generated always as` statement.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('full_name', 'varchar(255)',\n   *     (col) => col.generatedAlwaysAs(sql`concat(first_name, ' ', last_name)`)\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `full_name` varchar(255) generated always as (concat(first_name, ' ', last_name))\n   * )\n   * ```\n   */\n  generatedAlwaysAs(expression: Expression<any>): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, {\n        generated: GeneratedNode.createWithExpression(\n          expression.toOperationNode(),\n        ),\n      }),\n    )\n  }\n\n  /**\n   * Adds the `generated always as identity` specifier.\n   *\n   * This only works on some dialects like PostgreSQL.\n   *\n   * For MS SQL Server (MSSQL)'s identity column use {@link identity}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.generatedAlwaysAsIdentity().primaryKey())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create table \"person\" (\n   *   \"id\" integer generated always as identity primary key\n   * )\n   * ```\n   */\n  generatedAlwaysAsIdentity(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, {\n        generated: GeneratedNode.create({ identity: true, always: true }),\n      }),\n    )\n  }\n\n  /**\n   * Adds the `generated by default as identity` specifier on supported dialects.\n   *\n   * This only works on some dialects like PostgreSQL.\n   *\n   * For MS SQL Server (MSSQL)'s identity column use {@link identity}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.generatedByDefaultAsIdentity().primaryKey())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create table \"person\" (\n   *   \"id\" integer generated by default as identity primary key\n   * )\n   * ```\n   */\n  generatedByDefaultAsIdentity(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, {\n        generated: GeneratedNode.create({ identity: true, byDefault: true }),\n      }),\n    )\n  }\n\n  /**\n   * Makes a generated column stored instead of virtual. This method can only\n   * be used with {@link generatedAlwaysAs}\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('full_name', 'varchar(255)', (col) => col\n   *     .generatedAlwaysAs(sql`concat(first_name, ' ', last_name)`)\n   *     .stored()\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `full_name` varchar(255) generated always as (concat(first_name, ' ', last_name)) stored\n   * )\n   * ```\n   */\n  stored(): ColumnDefinitionBuilder {\n    if (!this.#node.generated) {\n      throw new Error('stored() can only be called after generatedAlwaysAs')\n    }\n\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, {\n        generated: GeneratedNode.cloneWith(this.#node.generated, {\n          stored: true,\n        }),\n      }),\n    )\n  }\n\n  /**\n   * This can be used to add any additional SQL right after the column's data type.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.primaryKey())\n   *   .addColumn(\n   *     'first_name',\n   *     'varchar(36)',\n   *     (col) => col.modifyFront(sql`collate utf8mb4_general_ci`).notNull()\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `id` integer primary key,\n   *   `first_name` varchar(36) collate utf8mb4_general_ci not null\n   * )\n   * ```\n   */\n  modifyFront(modifier: Expression<any>): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWithFrontModifier(\n        this.#node,\n        modifier.toOperationNode(),\n      ),\n    )\n  }\n\n  /**\n   * Adds `nulls not distinct` specifier.\n   * Should be used with `unique` constraint.\n   *\n   * This only works on some dialects like PostgreSQL.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.primaryKey())\n   *   .addColumn('first_name', 'varchar(30)', col => col.unique().nullsNotDistinct())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create table \"person\" (\n   *   \"id\" integer primary key,\n   *   \"first_name\" varchar(30) unique nulls not distinct\n   * )\n   * ```\n   */\n  nullsNotDistinct(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, { nullsNotDistinct: true }),\n    )\n  }\n\n  /**\n   * Adds `if not exists` specifier. This only works for PostgreSQL.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .alterTable('person')\n   *   .addColumn('email', 'varchar(255)', col => col.unique().ifNotExists())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * alter table \"person\" add column if not exists \"email\" varchar(255) unique\n   * ```\n   */\n  ifNotExists(): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWith(this.#node, { ifNotExists: true }),\n    )\n  }\n\n  /**\n   * This can be used to add any additional SQL to the end of the column definition.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.primaryKey())\n   *   .addColumn(\n   *     'age',\n   *     'integer',\n   *     col => col.unsigned()\n   *       .notNull()\n   *       .modifyEnd(sql`comment ${sql.lit('it is not polite to ask a woman her age')}`)\n   *   )\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `id` integer primary key,\n   *   `age` integer unsigned not null comment 'it is not polite to ask a woman her age'\n   * )\n   * ```\n   */\n  modifyEnd(modifier: Expression<any>): ColumnDefinitionBuilder {\n    return new ColumnDefinitionBuilder(\n      ColumnDefinitionNode.cloneWithEndModifier(\n        this.#node,\n        modifier.toOperationNode(),\n      ),\n    )\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): ColumnDefinitionNode {\n    return this.#node\n  }\n}\n\nexport type ColumnDefinitionBuilderCallback = (\n  builder: ColumnDefinitionBuilder,\n) => ColumnDefinitionBuilder\n"
  },
  {
    "path": "src/schema/create-index-builder.ts",
    "content": "import {\n  CreateIndexNode,\n  type IndexType,\n} from '../operation-node/create-index-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { RawNode } from '../operation-node/raw-node.js'\nimport {\n  type ExtractColumnNameFromOrderedColumnName,\n  type OrderedColumnName,\n  parseOrderedColumnName,\n} from '../parser/reference-parser.js'\nimport { parseTable } from '../parser/table-parser.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\nimport type { Expression } from '../expression/expression.js'\nimport {\n  type ComparisonOperatorExpression,\n  parseValueBinaryOperationOrExpression,\n} from '../parser/binary-operation-parser.js'\nimport { QueryNode } from '../operation-node/query-node.js'\nimport type { ExpressionBuilder } from '../expression/expression-builder.js'\nimport type { ShallowRecord, SqlBool } from '../util/type-utils.js'\nimport { ImmediateValueTransformer } from '../plugin/immediate-value/immediate-value-transformer.js'\n\nexport class CreateIndexBuilder<C = never>\n  implements OperationNodeSource, Compilable\n{\n  readonly #props: CreateIndexBuilderProps\n\n  constructor(props: CreateIndexBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Adds the \"if not exists\" modifier.\n   *\n   * If the index already exists, no error is thrown if this method has been called.\n   */\n  ifNotExists(): CreateIndexBuilder<C> {\n    return new CreateIndexBuilder({\n      ...this.#props,\n      node: CreateIndexNode.cloneWith(this.#props.node, {\n        ifNotExists: true,\n      }),\n    })\n  }\n\n  /**\n   * Makes the index unique.\n   */\n  unique(): CreateIndexBuilder<C> {\n    return new CreateIndexBuilder({\n      ...this.#props,\n      node: CreateIndexNode.cloneWith(this.#props.node, {\n        unique: true,\n      }),\n    })\n  }\n\n  /**\n   * Adds `nulls not distinct` specifier to index.\n   * This only works on some dialects like PostgreSQL.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * db.schema.createIndex('person_first_name_index')\n   *  .on('person')\n   *  .column('first_name')\n   *  .nullsNotDistinct()\n   *  .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create index \"person_first_name_index\"\n   * on \"test\" (\"first_name\")\n   * nulls not distinct;\n   * ```\n   */\n  nullsNotDistinct(): CreateIndexBuilder<C> {\n    return new CreateIndexBuilder({\n      ...this.#props,\n      node: CreateIndexNode.cloneWith(this.#props.node, {\n        nullsNotDistinct: true,\n      }),\n    })\n  }\n\n  /**\n   * Specifies the table for the index.\n   */\n  on(table: string): CreateIndexBuilder<C> {\n    return new CreateIndexBuilder({\n      ...this.#props,\n      node: CreateIndexNode.cloneWith(this.#props.node, {\n        table: parseTable(table),\n      }),\n    })\n  }\n\n  /**\n   * Adds a column to the index.\n   *\n   * Also see {@link columns} for adding multiple columns at once or {@link expression}\n   * for specifying an arbitrary expression.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *         .createIndex('person_first_name_and_age_index')\n   *         .on('person')\n   *         .column('first_name')\n   *         .column('age desc')\n   *         .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create index \"person_first_name_and_age_index\" on \"person\" (\"first_name\", \"age\" desc)\n   * ```\n   */\n  column<CL extends string>(\n    column: OrderedColumnName<CL>,\n  ): CreateIndexBuilder<C | ExtractColumnNameFromOrderedColumnName<CL>> {\n    return new CreateIndexBuilder({\n      ...this.#props,\n      node: CreateIndexNode.cloneWithColumns(this.#props.node, [\n        parseOrderedColumnName(column),\n      ]),\n    })\n  }\n\n  /**\n   * Specifies a list of columns for the index.\n   *\n   * Also see {@link column} for adding a single column or {@link expression} for\n   * specifying an arbitrary expression.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *         .createIndex('person_first_name_and_age_index')\n   *         .on('person')\n   *         .columns(['first_name', 'age desc'])\n   *         .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create index \"person_first_name_and_age_index\" on \"person\" (\"first_name\", \"age\" desc)\n   * ```\n   */\n  columns<CL extends string>(\n    columns: OrderedColumnName<CL>[],\n  ): CreateIndexBuilder<C | ExtractColumnNameFromOrderedColumnName<CL>> {\n    return new CreateIndexBuilder({\n      ...this.#props,\n      node: CreateIndexNode.cloneWithColumns(\n        this.#props.node,\n        columns.map(parseOrderedColumnName),\n      ),\n    })\n  }\n\n  /**\n   * Specifies an arbitrary expression for the index.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createIndex('person_first_name_index')\n   *   .on('person')\n   *   .expression(sql`first_name COLLATE \"fi_FI\"`)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create index \"person_first_name_index\" on \"person\" (first_name COLLATE \"fi_FI\")\n   * ```\n   */\n  expression(expression: Expression<any>): CreateIndexBuilder<C> {\n    return new CreateIndexBuilder({\n      ...this.#props,\n      node: CreateIndexNode.cloneWithColumns(this.#props.node, [\n        expression.toOperationNode(),\n      ]),\n    })\n  }\n\n  /**\n   * Specifies the index type.\n   */\n  using(indexType: IndexType): CreateIndexBuilder<C>\n  using(indexType: string): CreateIndexBuilder<C>\n  using(indexType: string): CreateIndexBuilder<C> {\n    return new CreateIndexBuilder({\n      ...this.#props,\n      node: CreateIndexNode.cloneWith(this.#props.node, {\n        using: RawNode.createWithSql(indexType),\n      }),\n    })\n  }\n\n  /**\n   * Adds a where clause to the query. This Effectively turns the index partial.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *    .createIndex('orders_unbilled_index')\n   *    .on('orders')\n   *    .column('order_nr')\n   *    .where(sql.ref('billed'), 'is not', true)\n   *    .where('order_nr', 'like', '123%')\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create index \"orders_unbilled_index\" on \"orders\" (\"order_nr\") where \"billed\" is not true and \"order_nr\" like '123%'\n   * ```\n   *\n   * Column names specified in {@link column} or {@link columns} are known at compile-time\n   * and can be referred to in the current query and context.\n   *\n   * Sometimes you may want to refer to columns that exist in the table but are not\n   * part of the current index. In that case you can refer to them using {@link sql}\n   * expressions.\n   *\n   * Parameters are always sent as literals due to database restrictions.\n   */\n  where(\n    lhs: C | Expression<any>,\n    op: ComparisonOperatorExpression,\n    rhs: unknown,\n  ): CreateIndexBuilder<C>\n\n  where(\n    factory: (\n      qb: ExpressionBuilder<\n        ShallowRecord<string, ShallowRecord<C & string, any>>,\n        string\n      >,\n    ) => Expression<SqlBool>,\n  ): CreateIndexBuilder<C>\n\n  where(expression: Expression<SqlBool>): CreateIndexBuilder<C>\n\n  where(...args: any[]): any {\n    const transformer = new ImmediateValueTransformer()\n\n    return new CreateIndexBuilder({\n      ...this.#props,\n      node: QueryNode.cloneWithWhere(\n        this.#props.node,\n        transformer.transformNode(\n          parseValueBinaryOperationOrExpression(args),\n          this.#props.queryId,\n        ),\n      ),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): CreateIndexNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface CreateIndexBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: CreateIndexNode\n}\n"
  },
  {
    "path": "src/schema/create-schema-builder.ts",
    "content": "import { CreateSchemaNode } from '../operation-node/create-schema-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport class CreateSchemaBuilder implements OperationNodeSource, Compilable {\n  readonly #props: CreateSchemaBuilderProps\n\n  constructor(props: CreateSchemaBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  ifNotExists(): CreateSchemaBuilder {\n    return new CreateSchemaBuilder({\n      ...this.#props,\n      node: CreateSchemaNode.cloneWith(this.#props.node, { ifNotExists: true }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): CreateSchemaNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface CreateSchemaBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: CreateSchemaNode\n}\n"
  },
  {
    "path": "src/schema/create-table-builder.ts",
    "content": "import { ColumnDefinitionNode } from '../operation-node/column-definition-node.js'\nimport {\n  CreateTableNode,\n  type OnCommitAction,\n} from '../operation-node/create-table-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport { ColumnDefinitionBuilder } from './column-definition-builder.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze, noop } from '../util/object-utils.js'\nimport { ForeignKeyConstraintNode } from '../operation-node/foreign-key-constraint-node.js'\nimport { ColumnNode } from '../operation-node/column-node.js'\nimport {\n  ForeignKeyConstraintBuilder,\n  type ForeignKeyConstraintBuilderCallback,\n} from './foreign-key-constraint-builder.js'\nimport {\n  type DataTypeExpression,\n  parseDataTypeExpression,\n} from '../parser/data-type-parser.js'\nimport { PrimaryKeyConstraintNode } from '../operation-node/primary-key-constraint-node.js'\nimport { UniqueConstraintNode } from '../operation-node/unique-constraint-node.js'\nimport { CheckConstraintNode } from '../operation-node/check-constraint-node.js'\nimport { parseTable } from '../parser/table-parser.js'\nimport { parseOnCommitAction } from '../parser/on-commit-action-parse.js'\nimport type { Expression } from '../expression/expression.js'\nimport {\n  UniqueConstraintNodeBuilder,\n  type UniqueConstraintNodeBuilderCallback,\n} from './unique-constraint-builder.js'\nimport { parseExpression } from '../parser/expression-parser.js'\nimport {\n  PrimaryKeyConstraintBuilder,\n  type PrimaryKeyConstraintBuilderCallback,\n} from './primary-key-constraint-builder.js'\nimport {\n  CheckConstraintBuilder,\n  type CheckConstraintBuilderCallback,\n} from './check-constraint-builder.js'\n\n/**\n * This builder can be used to create a `create table` query.\n */\nexport class CreateTableBuilder<TB extends string, C extends string = never>\n  implements OperationNodeSource, Compilable\n{\n  readonly #props: CreateTableBuilderProps\n\n  constructor(props: CreateTableBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Adds the \"temporary\" modifier.\n   *\n   * Use this to create a temporary table.\n   */\n  temporary(): CreateTableBuilder<TB, C> {\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWith(this.#props.node, {\n        temporary: true,\n      }),\n    })\n  }\n\n  /**\n   * Adds an \"on commit\" statement.\n   *\n   * This can be used in conjunction with temporary tables on supported databases\n   * like PostgreSQL.\n   */\n  onCommit(onCommit: OnCommitAction): CreateTableBuilder<TB, C> {\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWith(this.#props.node, {\n        onCommit: parseOnCommitAction(onCommit),\n      }),\n    })\n  }\n\n  /**\n   * Adds the \"if not exists\" modifier.\n   *\n   * If the table already exists, no error is thrown if this method has been called.\n   */\n  ifNotExists(): CreateTableBuilder<TB, C> {\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWith(this.#props.node, {\n        ifNotExists: true,\n      }),\n    })\n  }\n\n  /**\n   * Adds a column to the table.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', (col) => col.autoIncrement().primaryKey())\n   *   .addColumn('first_name', 'varchar(50)', (col) => col.notNull())\n   *   .addColumn('last_name', 'varchar(255)')\n   *   .addColumn('bank_balance', 'numeric(8, 2)')\n   *   // You can specify any data type using the `sql` tag if the types\n   *   // don't include it.\n   *   .addColumn('data', sql`any_type_here`)\n   *   .addColumn('parent_id', 'integer', (col) =>\n   *     col.references('person.id').onDelete('cascade')\n   *   )\n   * ```\n   *\n   * With this method, it's once again good to remember that Kysely just builds the\n   * query and doesn't provide the same API for all databases. For example, some\n   * databases like older MySQL don't support the `references` statement in the\n   * column definition. Instead foreign key constraints need to be defined in the\n   * `create table` query. See the next example:\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', (col) => col.primaryKey())\n   *   .addColumn('parent_id', 'integer')\n   *   .addForeignKeyConstraint(\n   *     'person_parent_id_fk',\n   *     ['parent_id'],\n   *     'person',\n   *     ['id'],\n   *     (cb) => cb.onDelete('cascade')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * Another good example is that PostgreSQL doesn't support the `auto_increment`\n   * keyword and you need to define an autoincrementing column for example using\n   * `serial`:\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'serial', (col) => col.primaryKey())\n   *   .execute()\n   * ```\n   */\n  addColumn<CN extends string>(\n    columnName: CN,\n    dataType: DataTypeExpression,\n    build: ColumnBuilderCallback = noop,\n  ): CreateTableBuilder<TB, C | CN> {\n    const columnBuilder = build(\n      new ColumnDefinitionBuilder(\n        ColumnDefinitionNode.create(\n          columnName,\n          parseDataTypeExpression(dataType),\n        ),\n      ),\n    )\n\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWithColumn(\n        this.#props.node,\n        columnBuilder.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Adds a primary key constraint for one or more columns.\n   *\n   * The constraint name can be anything you want, but it must be unique\n   * across the whole database.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('first_name', 'varchar(64)')\n   *   .addColumn('last_name', 'varchar(64)')\n   *   .addPrimaryKeyConstraint('primary_key', ['first_name', 'last_name'])\n   *   .execute()\n   * ```\n   */\n  addPrimaryKeyConstraint(\n    constraintName: string,\n    columns: C[],\n    build: PrimaryKeyConstraintBuilderCallback = noop,\n  ): CreateTableBuilder<TB, C> {\n    const constraintBuilder = build(\n      new PrimaryKeyConstraintBuilder(\n        PrimaryKeyConstraintNode.create(columns, constraintName),\n      ),\n    )\n\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWithConstraint(\n        this.#props.node,\n        constraintBuilder.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Adds a unique constraint for one or more columns.\n   *\n   * The constraint name can be anything you want, but it must be unique\n   * across the whole database.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('first_name', 'varchar(64)')\n   *   .addColumn('last_name', 'varchar(64)')\n   *   .addUniqueConstraint(\n   *     'first_name_last_name_unique',\n   *     ['first_name', 'last_name']\n   *   )\n   *   .execute()\n   * ```\n   *\n   * In dialects such as PostgreSQL you can specify `nulls not distinct` as follows:\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('first_name', 'varchar(64)')\n   *   .addColumn('last_name', 'varchar(64)')\n   *   .addUniqueConstraint(\n   *     'first_name_last_name_unique',\n   *     ['first_name', 'last_name'],\n   *     (cb) => cb.nullsNotDistinct()\n   *   )\n   *   .execute()\n   * ```\n   */\n  addUniqueConstraint(\n    constraintName: string,\n    columns: C[],\n    build: UniqueConstraintNodeBuilderCallback = noop,\n  ): CreateTableBuilder<TB, C> {\n    const uniqueConstraintBuilder = build(\n      new UniqueConstraintNodeBuilder(\n        UniqueConstraintNode.create(columns, constraintName),\n      ),\n    )\n\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWithConstraint(\n        this.#props.node,\n        uniqueConstraintBuilder.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Adds a check constraint.\n   *\n   * The constraint name can be anything you want, but it must be unique\n   * across the whole database.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('animal')\n   *   .addColumn('number_of_legs', 'integer')\n   *   .addCheckConstraint('check_legs', sql`number_of_legs < 5`)\n   *   .execute()\n   * ```\n   */\n  addCheckConstraint(\n    constraintName: string,\n    checkExpression: Expression<any>,\n    build: CheckConstraintBuilderCallback = noop,\n  ): CreateTableBuilder<TB, C> {\n    const constraintBuilder = build(\n      new CheckConstraintBuilder(\n        CheckConstraintNode.create(\n          checkExpression.toOperationNode(),\n          constraintName,\n        ),\n      ),\n    )\n\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWithConstraint(\n        this.#props.node,\n        constraintBuilder.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Adds a foreign key constraint.\n   *\n   * The constraint name can be anything you want, but it must be unique\n   * across the whole database.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn('owner_id', 'integer')\n   *   .addForeignKeyConstraint(\n   *     'owner_id_foreign',\n   *     ['owner_id'],\n   *     'person',\n   *     ['id'],\n   *   )\n   *   .execute()\n   * ```\n   *\n   * Add constraint for multiple columns:\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn('owner_id1', 'integer')\n   *   .addColumn('owner_id2', 'integer')\n   *   .addForeignKeyConstraint(\n   *     'owner_id_foreign',\n   *     ['owner_id1', 'owner_id2'],\n   *     'person',\n   *     ['id1', 'id2'],\n   *     (cb) => cb.onDelete('cascade')\n   *   )\n   *   .execute()\n   * ```\n   */\n  addForeignKeyConstraint(\n    constraintName: string,\n    columns: C[],\n    targetTable: string,\n    targetColumns: string[],\n    build: ForeignKeyConstraintBuilderCallback = noop,\n  ): CreateTableBuilder<TB, C> {\n    const builder = build(\n      new ForeignKeyConstraintBuilder(\n        ForeignKeyConstraintNode.create(\n          columns.map(ColumnNode.create),\n          parseTable(targetTable),\n          targetColumns.map(ColumnNode.create),\n          constraintName,\n        ),\n      ),\n    )\n\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWithConstraint(\n        this.#props.node,\n        builder.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * This can be used to add any additional SQL to the front of the query __after__ the `create` keyword.\n   *\n   * Also see {@link temporary}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('person')\n   *   .modifyFront(sql`global temporary`)\n   *   .addColumn('id', 'integer', col => col.primaryKey())\n   *   .addColumn('first_name', 'varchar(64)', col => col.notNull())\n   *   .addColumn('last_name', 'varchar(64)', col => col.notNull())\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (Postgres):\n   *\n   * ```sql\n   * create global temporary table \"person\" (\n   *   \"id\" integer primary key,\n   *   \"first_name\" varchar(64) not null,\n   *   \"last_name\" varchar(64) not null\n   * )\n   * ```\n   */\n  modifyFront(modifier: Expression<any>): CreateTableBuilder<TB, C> {\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWithFrontModifier(\n        this.#props.node,\n        modifier.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * This can be used to add any additional SQL to the end of the query.\n   *\n   * Also see {@link onCommit}.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.primaryKey())\n   *   .addColumn('first_name', 'varchar(64)', col => col.notNull())\n   *   .addColumn('last_name', 'varchar(64)', col => col.notNull())\n   *   .modifyEnd(sql`collate utf8_unicode_ci`)\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * create table `person` (\n   *   `id` integer primary key,\n   *   `first_name` varchar(64) not null,\n   *   `last_name` varchar(64) not null\n   * ) collate utf8_unicode_ci\n   * ```\n   */\n  modifyEnd(modifier: Expression<any>): CreateTableBuilder<TB, C> {\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWithEndModifier(\n        this.#props.node,\n        modifier.toOperationNode(),\n      ),\n    })\n  }\n\n  /**\n   * Allows to create table from `select` query.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('copy')\n   *   .temporary()\n   *   .as(db.selectFrom('person').select(['first_name', 'last_name']))\n   *   .execute()\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * create temporary table \"copy\" as\n   * select \"first_name\", \"last_name\" from \"person\"\n   * ```\n   */\n  as(expression: Expression<unknown>): CreateTableBuilder<TB, C> {\n    return new CreateTableBuilder({\n      ...this.#props,\n      node: CreateTableNode.cloneWith(this.#props.node, {\n        selectQuery: parseExpression(expression),\n      }),\n    })\n  }\n\n  /**\n   * Calls the given function passing `this` as the only argument.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('test')\n   *   .$call((builder) => builder.addColumn('id', 'integer'))\n   *   .execute()\n   * ```\n   *\n   * This is useful for creating reusable functions that can be called with a builder.\n   *\n   * ```ts\n   * import { type CreateTableBuilder, sql } from 'kysely'\n   *\n   * const addDefaultColumns = (ctb: CreateTableBuilder<any, any>) => {\n   *   return ctb\n   *     .addColumn('id', 'integer', (col) => col.notNull())\n   *     .addColumn('created_at', 'date', (col) =>\n   *       col.notNull().defaultTo(sql`now()`)\n   *     )\n   *     .addColumn('updated_at', 'date', (col) =>\n   *       col.notNull().defaultTo(sql`now()`)\n   *     )\n   * }\n   *\n   * await db.schema\n   *   .createTable('test')\n   *   .$call(addDefaultColumns)\n   *   .execute()\n   * ```\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): CreateTableNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface CreateTableBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: CreateTableNode\n}\n\nexport type ColumnBuilderCallback = (\n  builder: ColumnDefinitionBuilder,\n) => ColumnDefinitionBuilder\n"
  },
  {
    "path": "src/schema/create-type-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\nimport { CreateTypeNode } from '../operation-node/create-type-node.js'\n\nexport class CreateTypeBuilder implements OperationNodeSource, Compilable {\n  readonly #props: CreateTypeBuilderProps\n\n  constructor(props: CreateTypeBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  toOperationNode(): CreateTypeNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  /**\n   * Creates an anum type.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * db.schema.createType('species').asEnum(['cat', 'dog', 'frog'])\n   * ```\n   */\n  asEnum(values: readonly string[]): CreateTypeBuilder {\n    return new CreateTypeBuilder({\n      ...this.#props,\n      node: CreateTypeNode.cloneWithEnum(this.#props.node, values),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface CreateTypeBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: CreateTypeNode\n}\n"
  },
  {
    "path": "src/schema/create-view-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\nimport { CreateViewNode } from '../operation-node/create-view-node.js'\nimport { parseColumnName } from '../parser/reference-parser.js'\nimport { ImmediateValuePlugin } from '../plugin/immediate-value/immediate-value-plugin.js'\nimport type { RawBuilder } from '../raw-builder/raw-builder.js'\nimport type { SelectQueryBuilder } from '../query-builder/select-query-builder.js'\n\nexport class CreateViewBuilder implements OperationNodeSource, Compilable {\n  readonly #props: CreateViewBuilderProps\n\n  constructor(props: CreateViewBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Adds the \"temporary\" modifier.\n   *\n   * Use this to create a temporary view.\n   */\n  temporary(): CreateViewBuilder {\n    return new CreateViewBuilder({\n      ...this.#props,\n      node: CreateViewNode.cloneWith(this.#props.node, {\n        temporary: true,\n      }),\n    })\n  }\n\n  materialized(): CreateViewBuilder {\n    return new CreateViewBuilder({\n      ...this.#props,\n      node: CreateViewNode.cloneWith(this.#props.node, {\n        materialized: true,\n      }),\n    })\n  }\n\n  /**\n   * Only implemented on some dialects like SQLite. On most dialects, use {@link orReplace}.\n   */\n  ifNotExists(): CreateViewBuilder {\n    return new CreateViewBuilder({\n      ...this.#props,\n      node: CreateViewNode.cloneWith(this.#props.node, {\n        ifNotExists: true,\n      }),\n    })\n  }\n\n  orReplace(): CreateViewBuilder {\n    return new CreateViewBuilder({\n      ...this.#props,\n      node: CreateViewNode.cloneWith(this.#props.node, {\n        orReplace: true,\n      }),\n    })\n  }\n\n  columns(columns: string[]): CreateViewBuilder {\n    return new CreateViewBuilder({\n      ...this.#props,\n      node: CreateViewNode.cloneWith(this.#props.node, {\n        columns: columns.map(parseColumnName),\n      }),\n    })\n  }\n\n  /**\n   * Sets the select query or a `values` statement that creates the view.\n   *\n   * WARNING!\n   * Some dialects don't support parameterized queries in DDL statements and therefore\n   * the query or raw {@link sql } expression passed here is interpolated into a single\n   * string opening an SQL injection vulnerability. DO NOT pass unchecked user input\n   * into the query or raw expression passed to this method!\n   */\n  as(\n    query: SelectQueryBuilder<any, any, any> | RawBuilder<any>,\n  ): CreateViewBuilder {\n    const queryNode = query\n      .withPlugin(new ImmediateValuePlugin())\n      .toOperationNode()\n\n    return new CreateViewBuilder({\n      ...this.#props,\n      node: CreateViewNode.cloneWith(this.#props.node, {\n        as: queryNode,\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): CreateViewNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface CreateViewBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: CreateViewNode\n}\n"
  },
  {
    "path": "src/schema/drop-index-builder.ts",
    "content": "import { DropIndexNode } from '../operation-node/drop-index-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { parseTable } from '../parser/table-parser.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport class DropIndexBuilder implements OperationNodeSource, Compilable {\n  readonly #props: DropIndexBuilderProps\n\n  constructor(props: DropIndexBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Specifies the table the index was created for. This is not needed\n   * in all dialects.\n   */\n  on(table: string): DropIndexBuilder {\n    return new DropIndexBuilder({\n      ...this.#props,\n      node: DropIndexNode.cloneWith(this.#props.node, {\n        table: parseTable(table),\n      }),\n    })\n  }\n\n  ifExists(): DropIndexBuilder {\n    return new DropIndexBuilder({\n      ...this.#props,\n      node: DropIndexNode.cloneWith(this.#props.node, {\n        ifExists: true,\n      }),\n    })\n  }\n\n  cascade(): DropIndexBuilder {\n    return new DropIndexBuilder({\n      ...this.#props,\n      node: DropIndexNode.cloneWith(this.#props.node, {\n        cascade: true,\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): DropIndexNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface DropIndexBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: DropIndexNode\n}\n"
  },
  {
    "path": "src/schema/drop-schema-builder.ts",
    "content": "import { DropSchemaNode } from '../operation-node/drop-schema-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport class DropSchemaBuilder implements OperationNodeSource, Compilable {\n  readonly #props: DropSchemaBuilderProps\n\n  constructor(props: DropSchemaBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  ifExists(): DropSchemaBuilder {\n    return new DropSchemaBuilder({\n      ...this.#props,\n      node: DropSchemaNode.cloneWith(this.#props.node, {\n        ifExists: true,\n      }),\n    })\n  }\n\n  cascade(): DropSchemaBuilder {\n    return new DropSchemaBuilder({\n      ...this.#props,\n      node: DropSchemaNode.cloneWith(this.#props.node, {\n        cascade: true,\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): DropSchemaNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface DropSchemaBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: DropSchemaNode\n}\n"
  },
  {
    "path": "src/schema/drop-table-builder.ts",
    "content": "import { DropTableNode } from '../operation-node/drop-table-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport class DropTableBuilder implements OperationNodeSource, Compilable {\n  readonly #props: DropTableBuilderProps\n\n  constructor(props: DropTableBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  ifExists(): DropTableBuilder {\n    return new DropTableBuilder({\n      ...this.#props,\n      node: DropTableNode.cloneWith(this.#props.node, {\n        ifExists: true,\n      }),\n    })\n  }\n\n  cascade(): DropTableBuilder {\n    return new DropTableBuilder({\n      ...this.#props,\n      node: DropTableNode.cloneWith(this.#props.node, {\n        cascade: true,\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): DropTableNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface DropTableBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: DropTableNode\n}\n"
  },
  {
    "path": "src/schema/drop-type-builder.ts",
    "content": "import { DropTypeNode } from '../operation-node/drop-type-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\n\nexport class DropTypeBuilder implements OperationNodeSource, Compilable {\n  readonly #props: DropTypeBuilderProps\n\n  constructor(props: DropTypeBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  ifExists(): DropTypeBuilder {\n    return new DropTypeBuilder({\n      ...this.#props,\n      node: DropTypeNode.cloneWith(this.#props.node, {\n        ifExists: true,\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): DropTypeNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface DropTypeBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: DropTypeNode\n}\n"
  },
  {
    "path": "src/schema/drop-view-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\nimport { DropViewNode } from '../operation-node/drop-view-node.js'\n\nexport class DropViewBuilder implements OperationNodeSource, Compilable {\n  readonly #props: DropViewBuilderProps\n\n  constructor(props: DropViewBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  materialized(): DropViewBuilder {\n    return new DropViewBuilder({\n      ...this.#props,\n      node: DropViewNode.cloneWith(this.#props.node, {\n        materialized: true,\n      }),\n    })\n  }\n\n  ifExists(): DropViewBuilder {\n    return new DropViewBuilder({\n      ...this.#props,\n      node: DropViewNode.cloneWith(this.#props.node, {\n        ifExists: true,\n      }),\n    })\n  }\n\n  cascade(): DropViewBuilder {\n    return new DropViewBuilder({\n      ...this.#props,\n      node: DropViewNode.cloneWith(this.#props.node, {\n        cascade: true,\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): DropViewNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface DropViewBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: DropViewNode\n}\n"
  },
  {
    "path": "src/schema/foreign-key-constraint-builder.ts",
    "content": "import { ForeignKeyConstraintNode } from '../operation-node/foreign-key-constraint-node.js'\nimport type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { OnModifyForeignAction } from '../operation-node/references-node.js'\nimport { parseOnModifyForeignAction } from '../parser/on-modify-action-parser.js'\n\nexport interface ForeignKeyConstraintBuilderInterface<R> {\n  onDelete(onDelete: OnModifyForeignAction): R\n  onUpdate(onUpdate: OnModifyForeignAction): R\n  deferrable(): R\n  notDeferrable(): R\n  initiallyDeferred(): R\n  initiallyImmediate(): R\n}\n\nexport class ForeignKeyConstraintBuilder\n  implements\n    ForeignKeyConstraintBuilderInterface<ForeignKeyConstraintBuilder>,\n    OperationNodeSource\n{\n  readonly #node: ForeignKeyConstraintNode\n\n  constructor(node: ForeignKeyConstraintNode) {\n    this.#node = node\n  }\n\n  onDelete(onDelete: OnModifyForeignAction): ForeignKeyConstraintBuilder {\n    return new ForeignKeyConstraintBuilder(\n      ForeignKeyConstraintNode.cloneWith(this.#node, {\n        onDelete: parseOnModifyForeignAction(onDelete),\n      }),\n    )\n  }\n\n  onUpdate(onUpdate: OnModifyForeignAction): ForeignKeyConstraintBuilder {\n    return new ForeignKeyConstraintBuilder(\n      ForeignKeyConstraintNode.cloneWith(this.#node, {\n        onUpdate: parseOnModifyForeignAction(onUpdate),\n      }),\n    )\n  }\n\n  deferrable(): ForeignKeyConstraintBuilder {\n    return new ForeignKeyConstraintBuilder(\n      ForeignKeyConstraintNode.cloneWith(this.#node, { deferrable: true }),\n    )\n  }\n\n  notDeferrable(): ForeignKeyConstraintBuilder {\n    return new ForeignKeyConstraintBuilder(\n      ForeignKeyConstraintNode.cloneWith(this.#node, { deferrable: false }),\n    )\n  }\n\n  initiallyDeferred(): ForeignKeyConstraintBuilder {\n    return new ForeignKeyConstraintBuilder(\n      ForeignKeyConstraintNode.cloneWith(this.#node, {\n        initiallyDeferred: true,\n      }),\n    )\n  }\n\n  initiallyImmediate(): ForeignKeyConstraintBuilder {\n    return new ForeignKeyConstraintBuilder(\n      ForeignKeyConstraintNode.cloneWith(this.#node, {\n        initiallyDeferred: false,\n      }),\n    )\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): ForeignKeyConstraintNode {\n    return this.#node\n  }\n}\n\nexport type ForeignKeyConstraintBuilderCallback = (\n  builder: ForeignKeyConstraintBuilder,\n) => ForeignKeyConstraintBuilder\n"
  },
  {
    "path": "src/schema/primary-key-constraint-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { PrimaryKeyConstraintNode } from '../operation-node/primary-key-constraint-node.js'\n\nexport class PrimaryKeyConstraintBuilder implements OperationNodeSource {\n  readonly #node: PrimaryKeyConstraintNode\n\n  constructor(node: PrimaryKeyConstraintNode) {\n    this.#node = node\n  }\n\n  deferrable(): PrimaryKeyConstraintBuilder {\n    return new PrimaryKeyConstraintBuilder(\n      PrimaryKeyConstraintNode.cloneWith(this.#node, { deferrable: true }),\n    )\n  }\n\n  notDeferrable(): PrimaryKeyConstraintBuilder {\n    return new PrimaryKeyConstraintBuilder(\n      PrimaryKeyConstraintNode.cloneWith(this.#node, { deferrable: false }),\n    )\n  }\n\n  initiallyDeferred(): PrimaryKeyConstraintBuilder {\n    return new PrimaryKeyConstraintBuilder(\n      PrimaryKeyConstraintNode.cloneWith(this.#node, {\n        initiallyDeferred: true,\n      }),\n    )\n  }\n\n  initiallyImmediate(): PrimaryKeyConstraintBuilder {\n    return new PrimaryKeyConstraintBuilder(\n      PrimaryKeyConstraintNode.cloneWith(this.#node, {\n        initiallyDeferred: false,\n      }),\n    )\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): PrimaryKeyConstraintNode {\n    return this.#node\n  }\n}\n\nexport type PrimaryKeyConstraintBuilderCallback = (\n  builder: PrimaryKeyConstraintBuilder,\n) => PrimaryKeyConstraintBuilder\n"
  },
  {
    "path": "src/schema/refresh-materialized-view-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from '../util/compilable.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport type { QueryId } from '../util/query-id.js'\nimport { freeze } from '../util/object-utils.js'\nimport { RefreshMaterializedViewNode } from '../operation-node/refresh-materialized-view-node.js'\n\nexport class RefreshMaterializedViewBuilder\n  implements OperationNodeSource, Compilable\n{\n  readonly #props: RefreshMaterializedViewBuilderProps\n\n  constructor(props: RefreshMaterializedViewBuilderProps) {\n    this.#props = freeze(props)\n  }\n\n  /**\n   * Adds the \"concurrently\" modifier.\n   *\n   * Use this to refresh the view without locking out concurrent selects on the materialized view.\n   *\n   * WARNING!\n   * This cannot be used with the \"with no data\" modifier.\n   */\n  concurrently(): RefreshMaterializedViewBuilder {\n    return new RefreshMaterializedViewBuilder({\n      ...this.#props,\n      node: RefreshMaterializedViewNode.cloneWith(this.#props.node, {\n        concurrently: true,\n        withNoData: false,\n      }),\n    })\n  }\n\n  /**\n   * Adds the \"with data\" modifier.\n   *\n   * If specified (or defaults) the backing query is executed to provide the new data, and the materialized view is left in a scannable state\n   */\n  withData(): RefreshMaterializedViewBuilder {\n    return new RefreshMaterializedViewBuilder({\n      ...this.#props,\n      node: RefreshMaterializedViewNode.cloneWith(this.#props.node, {\n        withNoData: false,\n      }),\n    })\n  }\n\n  /**\n   * Adds the \"with no data\" modifier.\n   *\n   * If specified, no new data is generated and the materialized view is left in an unscannable state.\n   *\n   * WARNING!\n   * This cannot be used with the \"concurrently\" modifier.\n   */\n  withNoData(): RefreshMaterializedViewBuilder {\n    return new RefreshMaterializedViewBuilder({\n      ...this.#props,\n      node: RefreshMaterializedViewNode.cloneWith(this.#props.node, {\n        withNoData: true,\n        concurrently: false,\n      }),\n    })\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): RefreshMaterializedViewNode {\n    return this.#props.executor.transformQuery(\n      this.#props.node,\n      this.#props.queryId,\n    )\n  }\n\n  compile(): CompiledQuery {\n    return this.#props.executor.compileQuery(\n      this.toOperationNode(),\n      this.#props.queryId,\n    )\n  }\n\n  async execute(): Promise<void> {\n    await this.#props.executor.executeQuery(this.compile())\n  }\n}\n\nexport interface RefreshMaterializedViewBuilderProps {\n  readonly queryId: QueryId\n  readonly executor: QueryExecutor\n  readonly node: RefreshMaterializedViewNode\n}\n"
  },
  {
    "path": "src/schema/schema.ts",
    "content": "import { AlterTableNode } from '../operation-node/alter-table-node.js'\nimport { CreateIndexNode } from '../operation-node/create-index-node.js'\nimport { CreateSchemaNode } from '../operation-node/create-schema-node.js'\nimport { CreateTableNode } from '../operation-node/create-table-node.js'\nimport { DropIndexNode } from '../operation-node/drop-index-node.js'\nimport { DropSchemaNode } from '../operation-node/drop-schema-node.js'\nimport { DropTableNode } from '../operation-node/drop-table-node.js'\nimport { parseTable } from '../parser/table-parser.js'\nimport type { QueryExecutor } from '../query-executor/query-executor.js'\nimport { AlterTableBuilder } from './alter-table-builder.js'\nimport { CreateIndexBuilder } from './create-index-builder.js'\nimport { CreateSchemaBuilder } from './create-schema-builder.js'\nimport { CreateTableBuilder } from './create-table-builder.js'\nimport { DropIndexBuilder } from './drop-index-builder.js'\nimport { DropSchemaBuilder } from './drop-schema-builder.js'\nimport { DropTableBuilder } from './drop-table-builder.js'\nimport { createQueryId } from '../util/query-id.js'\nimport { WithSchemaPlugin } from '../plugin/with-schema/with-schema-plugin.js'\nimport { CreateViewBuilder } from './create-view-builder.js'\nimport { CreateViewNode } from '../operation-node/create-view-node.js'\nimport { DropViewBuilder } from './drop-view-builder.js'\nimport { DropViewNode } from '../operation-node/drop-view-node.js'\nimport type { KyselyPlugin } from '../plugin/kysely-plugin.js'\nimport { CreateTypeBuilder } from './create-type-builder.js'\nimport { DropTypeBuilder } from './drop-type-builder.js'\nimport { CreateTypeNode } from '../operation-node/create-type-node.js'\nimport { DropTypeNode } from '../operation-node/drop-type-node.js'\nimport { parseSchemableIdentifier } from '../parser/identifier-parser.js'\nimport { RefreshMaterializedViewBuilder } from './refresh-materialized-view-builder.js'\nimport { RefreshMaterializedViewNode } from '../operation-node/refresh-materialized-view-node.js'\n\n/**\n * Provides methods for building database schema.\n */\nexport class SchemaModule {\n  readonly #executor: QueryExecutor\n\n  constructor(executor: QueryExecutor) {\n    this.#executor = executor\n  }\n\n  /**\n   * Create a new table.\n   *\n   * ### Examples\n   *\n   * This example creates a new table with columns `id`, `first_name`,\n   * `last_name` and `gender`:\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('person')\n   *   .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())\n   *   .addColumn('first_name', 'varchar', col => col.notNull())\n   *   .addColumn('last_name', 'varchar', col => col.notNull())\n   *   .addColumn('gender', 'varchar')\n   *   .execute()\n   * ```\n   *\n   * This example creates a table with a foreign key. Not all database\n   * engines support column-level foreign key constraint definitions.\n   * For example if you are using MySQL 5.X see the next example after\n   * this one.\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())\n   *   .addColumn('owner_id', 'integer', col => col\n   *     .references('person.id')\n   *     .onDelete('cascade')\n   *   )\n   *   .execute()\n   * ```\n   *\n   * This example adds a foreign key constraint for a columns just\n   * like the previous example, but using a table-level statement.\n   * On MySQL 5.X you need to define foreign key constraints like\n   * this:\n   *\n   * ```ts\n   * await db.schema\n   *   .createTable('pet')\n   *   .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())\n   *   .addColumn('owner_id', 'integer')\n   *   .addForeignKeyConstraint(\n   *     'pet_owner_id_foreign', ['owner_id'], 'person', ['id'],\n   *     (constraint) => constraint.onDelete('cascade')\n   *   )\n   *   .execute()\n   * ```\n   */\n  createTable<TB extends string>(table: TB): CreateTableBuilder<TB, never> {\n    return new CreateTableBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: CreateTableNode.create(parseTable(table)),\n    })\n  }\n\n  /**\n   * Drop a table.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .dropTable('person')\n   *   .execute()\n   * ```\n   */\n  dropTable(table: string): DropTableBuilder {\n    return new DropTableBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: DropTableNode.create(parseTable(table)),\n    })\n  }\n\n  /**\n   * Create a new index.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createIndex('person_full_name_unique_index')\n   *   .on('person')\n   *   .columns(['first_name', 'last_name'])\n   *   .execute()\n   * ```\n   */\n  createIndex(indexName: string): CreateIndexBuilder {\n    return new CreateIndexBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: CreateIndexNode.create(indexName),\n    })\n  }\n\n  /**\n   * Drop an index.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .dropIndex('person_full_name_unique_index')\n   *   .execute()\n   * ```\n   */\n  dropIndex(indexName: string): DropIndexBuilder {\n    return new DropIndexBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: DropIndexNode.create(indexName),\n    })\n  }\n\n  /**\n   * Create a new schema.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createSchema('some_schema')\n   *   .execute()\n   * ```\n   */\n  createSchema(schema: string): CreateSchemaBuilder {\n    return new CreateSchemaBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: CreateSchemaNode.create(schema),\n    })\n  }\n\n  /**\n   * Drop a schema.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .dropSchema('some_schema')\n   *   .execute()\n   * ```\n   */\n  dropSchema(schema: string): DropSchemaBuilder {\n    return new DropSchemaBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: DropSchemaNode.create(schema),\n    })\n  }\n\n  /**\n   * Alter a table.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .alterTable('person')\n   *   .alterColumn('first_name', (ac) => ac.setDataType('text'))\n   *   .execute()\n   * ```\n   */\n  alterTable(table: string): AlterTableBuilder {\n    return new AlterTableBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: AlterTableNode.create(parseTable(table)),\n    })\n  }\n\n  /**\n   * Create a new view.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createView('dogs')\n   *   .orReplace()\n   *   .as(db.selectFrom('pet').selectAll().where('species', '=', 'dog'))\n   *   .execute()\n   * ```\n   */\n  createView(viewName: string): CreateViewBuilder {\n    return new CreateViewBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: CreateViewNode.create(viewName),\n    })\n  }\n\n  /**\n   * Refresh a materialized view.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .refreshMaterializedView('my_view')\n   *   .concurrently()\n   *   .execute()\n   * ```\n   */\n  refreshMaterializedView(viewName: string): RefreshMaterializedViewBuilder {\n    return new RefreshMaterializedViewBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: RefreshMaterializedViewNode.create(viewName),\n    })\n  }\n\n  /**\n   * Drop a view.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .dropView('dogs')\n   *   .ifExists()\n   *   .execute()\n   * ```\n   */\n  dropView(viewName: string): DropViewBuilder {\n    return new DropViewBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: DropViewNode.create(viewName),\n    })\n  }\n\n  /**\n   * Create a new type.\n   *\n   * Only some dialects like PostgreSQL have user-defined types.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .createType('species')\n   *   .asEnum(['dog', 'cat', 'frog'])\n   *   .execute()\n   * ```\n   */\n  createType(typeName: string): CreateTypeBuilder {\n    return new CreateTypeBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: CreateTypeNode.create(parseSchemableIdentifier(typeName)),\n    })\n  }\n\n  /**\n   * Drop a type.\n   *\n   * Only some dialects like PostgreSQL have user-defined types.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * await db.schema\n   *   .dropType('species')\n   *   .ifExists()\n   *   .execute()\n   * ```\n   */\n  dropType(typeName: string): DropTypeBuilder {\n    return new DropTypeBuilder({\n      queryId: createQueryId(),\n      executor: this.#executor,\n      node: DropTypeNode.create(parseSchemableIdentifier(typeName)),\n    })\n  }\n\n  /**\n   * Returns a copy of this schema module with the given plugin installed.\n   */\n  withPlugin(plugin: KyselyPlugin): SchemaModule {\n    return new SchemaModule(this.#executor.withPlugin(plugin))\n  }\n\n  /**\n   * Returns a copy of this schema module  without any plugins.\n   */\n  withoutPlugins(): SchemaModule {\n    return new SchemaModule(this.#executor.withoutPlugins())\n  }\n\n  /**\n   * See {@link QueryCreator.withSchema}\n   */\n  withSchema(schema: string): SchemaModule {\n    return new SchemaModule(\n      this.#executor.withPluginAtFront(new WithSchemaPlugin(schema)),\n    )\n  }\n}\n"
  },
  {
    "path": "src/schema/unique-constraint-builder.ts",
    "content": "import type { OperationNodeSource } from '../operation-node/operation-node-source.js'\nimport { UniqueConstraintNode } from '../operation-node/unique-constraint-node.js'\n\nexport class UniqueConstraintNodeBuilder implements OperationNodeSource {\n  readonly #node: UniqueConstraintNode\n\n  constructor(node: UniqueConstraintNode) {\n    this.#node = node\n  }\n\n  /**\n   * Adds `nulls not distinct` to the unique constraint definition\n   *\n   * Supported by PostgreSQL dialect only\n   */\n  nullsNotDistinct(): UniqueConstraintNodeBuilder {\n    return new UniqueConstraintNodeBuilder(\n      UniqueConstraintNode.cloneWith(this.#node, { nullsNotDistinct: true }),\n    )\n  }\n\n  deferrable(): UniqueConstraintNodeBuilder {\n    return new UniqueConstraintNodeBuilder(\n      UniqueConstraintNode.cloneWith(this.#node, { deferrable: true }),\n    )\n  }\n\n  notDeferrable(): UniqueConstraintNodeBuilder {\n    return new UniqueConstraintNodeBuilder(\n      UniqueConstraintNode.cloneWith(this.#node, { deferrable: false }),\n    )\n  }\n\n  initiallyDeferred(): UniqueConstraintNodeBuilder {\n    return new UniqueConstraintNodeBuilder(\n      UniqueConstraintNode.cloneWith(this.#node, {\n        initiallyDeferred: true,\n      }),\n    )\n  }\n\n  initiallyImmediate(): UniqueConstraintNodeBuilder {\n    return new UniqueConstraintNodeBuilder(\n      UniqueConstraintNode.cloneWith(this.#node, {\n        initiallyDeferred: false,\n      }),\n    )\n  }\n\n  /**\n   * Simply calls the provided function passing `this` as the only argument. `$call` returns\n   * what the provided function returns.\n   */\n  $call<T>(func: (qb: this) => T): T {\n    return func(this)\n  }\n\n  toOperationNode(): UniqueConstraintNode {\n    return this.#node\n  }\n}\n\nexport type UniqueConstraintNodeBuilderCallback = (\n  builder: UniqueConstraintNodeBuilder,\n) => UniqueConstraintNodeBuilder\n"
  },
  {
    "path": "src/util/assert.ts",
    "content": "export function assertNotNullOrUndefined<T>(\n  value: T,\n): asserts value is NonNullable<T> {\n  if (value === null || value === undefined) {\n    throw new Error(`${value} must not be null or undefined`)\n  }\n}\n\nexport function assertIsString(value: any): asserts value is string {\n  if (typeof value !== 'string') {\n    throw new Error(`${value} must be a string`)\n  }\n}\n"
  },
  {
    "path": "src/util/column-type.ts",
    "content": "import type { DrainOuterGeneric } from './type-utils.js'\n\n/**\n * This type can be used to specify a different type for\n * select, insert and update operations.\n *\n * Also see the {@link Generated} type.\n *\n * ### Examples\n *\n * The next example defines a number column that is optional\n * in inserts and updates. All columns are always optional\n * in updates so therefore we don't need to specify `undefined`\n * for the update type. The type below is useful for all kinds of\n * database generated columns like identifiers. The `Generated`\n * type is actually just a shortcut for the type in this example:\n *\n * ```ts\n * type GeneratedNumber = ColumnType<number, number | undefined, number>\n * ```\n *\n * The above example makes the column optional in inserts\n * and updates, but you can still choose to provide the\n * column. If you want to prevent insertion/update you\n * can se the type as `never`:\n *\n * ```ts\n * type ReadonlyNumber = ColumnType<number, never, never>\n * ```\n *\n * Here's one more example where the type is different\n * for each different operation:\n *\n * ```ts\n * type UnupdateableDate = ColumnType<Date, string, never>\n * ```\n */\nexport type ColumnType<\n  SelectType,\n  InsertType = SelectType,\n  UpdateType = SelectType,\n> = {\n  readonly __select__: SelectType\n  readonly __insert__: InsertType\n  readonly __update__: UpdateType\n}\n\n/**\n * A shortcut for defining database-generated columns. The type\n * is the same for all selects, inserts and updates but the\n * column is optional for inserts and updates.\n *\n * The update type is `S` instead of `S | undefined` because updates are always\n * optional --> no need to specify optionality.\n * ```\n */\nexport type Generated<S> = ColumnType<S, S | undefined, S>\n\n/**\n * A shortcut for defining columns that are only database-generated\n * (like postgres GENERATED ALWAYS AS IDENTITY). No insert/update\n * is allowed.\n */\nexport type GeneratedAlways<S> = ColumnType<S, never, never>\n\n/**\n * A shortcut for defining JSON columns, which are by default inserted/updated\n * as stringified JSON strings.\n */\nexport type JSONColumnType<\n  SelectType extends object | null,\n  InsertType = string,\n  UpdateType = string,\n> = ColumnType<SelectType, InsertType, UpdateType>\n\n/**\n * Evaluates to `K` if `T` can be `null` or `undefined`.\n */\ntype IfNullable<T, K> = undefined extends T ? K : null extends T ? K : never\n\n/**\n * Evaluates to `K` if `T` can't be `null` or `undefined`.\n */\ntype IfNotNullable<T, K> = undefined extends T\n  ? never\n  : null extends T\n    ? never\n    : T extends never\n      ? never\n      : K\n\n/**\n * Evaluates to `K` if `T` isn't `never`.\n */\ntype IfNotNever<T, K> = T extends never ? never : K\n\nexport type SelectType<T> = T extends ColumnType<infer S, any, any> ? S : T\nexport type InsertType<T> = T extends ColumnType<any, infer I, any> ? I : T\nexport type UpdateType<T> = T extends ColumnType<any, any, infer U> ? U : T\n\n/**\n * Keys of `R` whose `InsertType` values can be `null` or `undefined`.\n */\nexport type NullableInsertKeys<R> = {\n  [K in keyof R]: IfNullable<InsertType<R[K]>, K>\n}[keyof R]\n\n/**\n * Keys of `R` whose `InsertType` values can't be `null` or `undefined`.\n */\nexport type NonNullableInsertKeys<R> = {\n  [K in keyof R]: IfNotNullable<InsertType<R[K]>, K>\n}[keyof R]\n\n/**\n * Keys of `R` whose `SelectType` values are not `never`\n */\ntype NonNeverSelectKeys<R> = {\n  [K in keyof R]: IfNotNever<SelectType<R[K]>, K>\n}[keyof R]\n\n/**\n * Keys of `R` whose `UpdateType` values are not `never`\n */\nexport type UpdateKeys<R> = {\n  [K in keyof R]: IfNotNever<UpdateType<R[K]>, K>\n}[keyof R]\n\n/**\n * Given a table interface, extracts the select type from all\n * {@link ColumnType} types.\n *\n * ### Examples\n *\n * ```ts\n * interface PersonTable {\n *   id: Generated<number>\n *   first_name: string\n *   modified_at: ColumnType<Date, string, never>\n * }\n *\n * type Person = Selectable<PersonTable>\n * // {\n * //   id: number,\n * //   first_name: string\n * //   modified_at: Date\n * // }\n * ```\n */\nexport type Selectable<R> = DrainOuterGeneric<{\n  [K in NonNeverSelectKeys<R>]: SelectType<R[K]>\n}>\n\n/**\n * Given a table interface, extracts the insert type from all\n * {@link ColumnType} types.\n *\n * ### Examples\n *\n * ```ts\n * interface PersonTable {\n *   id: Generated<number>\n *   first_name: string\n *   modified_at: ColumnType<Date, string, never>\n * }\n *\n * type InsertablePerson = Insertable<PersonTable>\n * // {\n * //   id?: number,\n * //   first_name: string\n * //   modified_at: string\n * // }\n * ```\n */\nexport type Insertable<R> = DrainOuterGeneric<\n  object & {\n    [K in NonNullableInsertKeys<R>]: InsertType<R[K]>\n  } & {\n    [K in NullableInsertKeys<R>]?: InsertType<R[K]>\n  }\n>\n\n/**\n * Given a table interface, extracts the update type from all\n * {@link ColumnType} types.\n *\n * ### Examples\n *\n * ```ts\n * interface PersonTable {\n *   id: Generated<number>\n *   first_name: string\n *   modified_at: ColumnType<Date, string, never>\n * }\n *\n * type UpdateablePerson = Updateable<PersonTable>\n * // {\n * //   id?: number,\n * //   first_name?: string\n * // }\n * ```\n */\nexport type Updateable<R> = DrainOuterGeneric<{\n  [K in UpdateKeys<R>]?: UpdateType<R[K]>\n}>\n"
  },
  {
    "path": "src/util/compilable.ts",
    "content": "import type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport { isFunction, isObject } from './object-utils.js'\n\nexport interface Compilable<O = unknown> {\n  compile(): CompiledQuery<O>\n}\n\nexport function isCompilable(value: unknown): value is Compilable {\n  return isObject(value) && isFunction(value.compile)\n}\n"
  },
  {
    "path": "src/util/deferred.ts",
    "content": "export class Deferred<T> {\n  readonly #promise: Promise<T>\n\n  #resolve?: (value: T | PromiseLike<T>) => void\n  #reject?: (reason?: any) => void\n\n  constructor() {\n    this.#promise = new Promise<T>((resolve, reject) => {\n      this.#reject = reject\n      this.#resolve = resolve\n    })\n  }\n\n  get promise(): Promise<T> {\n    return this.#promise\n  }\n\n  resolve = (value: T | PromiseLike<T>): void => {\n    if (this.#resolve) {\n      this.#resolve(value)\n    }\n  }\n\n  reject = (reason?: any): void => {\n    if (this.#reject) {\n      this.#reject(reason)\n    }\n  }\n}\n"
  },
  {
    "path": "src/util/explainable.ts",
    "content": "import type { Expression } from '../expression/expression.js'\n\nexport type ExplainFormat =\n  | 'text'\n  | 'xml'\n  | 'json'\n  | 'yaml'\n  | 'traditional'\n  | 'tree'\n\nexport interface Explainable {\n  /**\n   * Executes query with `explain` statement before the main query.\n   *\n   * ```ts\n   * const explained = await db\n   *  .selectFrom('person')\n   *  .where('gender', '=', 'female')\n   *  .selectAll()\n   *  .explain('json')\n   * ```\n   *\n   * The generated SQL (MySQL):\n   *\n   * ```sql\n   * explain format=json select * from `person` where `gender` = ?\n   * ```\n   *\n   * You can also execute `explain analyze` statements.\n   *\n   * ```ts\n   * import { sql } from 'kysely'\n   *\n   * const explained = await db\n   *  .selectFrom('person')\n   *  .where('gender', '=', 'female')\n   *  .selectAll()\n   *  .explain('json', sql`analyze`)\n   * ```\n   *\n   * The generated SQL (PostgreSQL):\n   *\n   * ```sql\n   * explain (analyze, format json) select * from \"person\" where \"gender\" = $1\n   * ```\n   */\n  explain<O extends Record<string, any> = Record<string, any>>(\n    format?: ExplainFormat,\n    options?: Expression<any>,\n  ): Promise<O[]>\n}\n"
  },
  {
    "path": "src/util/infer-result.ts",
    "content": "import type { DeleteResult } from '../query-builder/delete-result.js'\nimport type { InsertResult } from '../query-builder/insert-result.js'\nimport type { MergeResult } from '../query-builder/merge-result.js'\nimport type { UpdateResult } from '../query-builder/update-result.js'\nimport type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport type { Compilable } from './compilable.js'\nimport type { Simplify } from './type-utils.js'\n\n/**\n * A helper type that allows inferring a select/insert/update/delete query's result\n * type from a query builder or compiled query.\n *\n * ### Examples\n *\n * Infer a query builder's result type:\n *\n * ```ts\n * import { InferResult } from 'kysely'\n *\n * const query = db\n *   .selectFrom('person')\n *   .innerJoin('pet', 'pet.owner_id', 'person.id')\n *   .select(['person.first_name', 'pet.name'])\n *\n * type QueryResult = InferResult<typeof query> // { first_name: string; name: string; }[]\n * ```\n *\n * Infer a compiled query's result type:\n *\n * ```ts\n * import { InferResult } from 'kysely'\n *\n * const compiledQuery = db\n *   .insertInto('person')\n *   .values({\n *     first_name: 'Foo',\n *     last_name: 'Barson',\n *     gender: 'other',\n *     age: 15,\n *   })\n *   .returningAll()\n *   .compile()\n *\n * type QueryResult = InferResult<typeof compiledQuery> // Selectable<Person>[]\n * ```\n */\nexport type InferResult<C extends Compilable<any> | CompiledQuery<any>> =\n  C extends Compilable<infer O>\n    ? ResolveResult<O>\n    : C extends CompiledQuery<infer O>\n      ? ResolveResult<O>\n      : never\n\ntype ResolveResult<O> = O extends\n  | InsertResult\n  | UpdateResult\n  | DeleteResult\n  | MergeResult\n  ? O[]\n  : Simplify<O>[]\n"
  },
  {
    "path": "src/util/json-object-args.ts",
    "content": "import { ExpressionWrapper } from '../expression/expression-wrapper.js'\nimport type { Expression } from '../expression/expression.js'\nimport { AliasNode } from '../operation-node/alias-node.js'\nimport { ColumnNode } from '../operation-node/column-node.js'\nimport { IdentifierNode } from '../operation-node/identifier-node.js'\nimport { ReferenceNode } from '../operation-node/reference-node.js'\nimport type { SelectQueryNode } from '../operation-node/select-query-node.js'\nimport { TableNode } from '../operation-node/table-node.js'\nimport { ValueNode } from '../operation-node/value-node.js'\n\nexport function getJsonObjectArgs(\n  node: SelectQueryNode,\n  table: string,\n): Expression<unknown>[] {\n  const args: Expression<unknown>[] = []\n\n  for (const { selection: s } of node.selections ?? []) {\n    if (ReferenceNode.is(s) && ColumnNode.is(s.column)) {\n      args.push(\n        colName(s.column.column.name),\n        colRef(table, s.column.column.name),\n      )\n    } else if (ColumnNode.is(s)) {\n      args.push(colName(s.column.name), colRef(table, s.column.name))\n    } else if (AliasNode.is(s) && IdentifierNode.is(s.alias)) {\n      args.push(colName(s.alias.name), colRef(table, s.alias.name))\n    } else {\n      throw new Error(`can't extract column names from the select query node`)\n    }\n  }\n\n  return args\n}\n\nfunction colName(col: string): Expression<unknown> {\n  return new ExpressionWrapper(ValueNode.createImmediate(col))\n}\n\nfunction colRef(table: string, col: string): Expression<unknown> {\n  return new ExpressionWrapper(\n    ReferenceNode.create(ColumnNode.create(col), TableNode.create(table)),\n  )\n}\n"
  },
  {
    "path": "src/util/log-once.ts",
    "content": "const LOGGED_MESSAGES: Set<string> = new Set()\n\n/**\n * Use for system-level logging, such as deprecation messages.\n * Logs a message and ensures it won't be logged again.\n */\nexport function logOnce(message: string): void {\n  if (LOGGED_MESSAGES.has(message)) {\n    return\n  }\n\n  LOGGED_MESSAGES.add(message)\n  console.log(message)\n}\n"
  },
  {
    "path": "src/util/log.ts",
    "content": "import type { CompiledQuery } from '../query-compiler/compiled-query.js'\nimport { freeze, isFunction } from './object-utils.js'\nimport type { ArrayItemType } from './type-utils.js'\n\nconst logLevels = ['query', 'error'] as const\nexport const LOG_LEVELS: Readonly<typeof logLevels> = freeze(logLevels)\n\nexport type LogLevel = ArrayItemType<typeof LOG_LEVELS>\n\nexport interface QueryLogEvent {\n  readonly level: 'query'\n  readonly isStream?: boolean\n  readonly query: CompiledQuery\n  readonly queryDurationMillis: number\n}\n\nexport interface ErrorLogEvent {\n  readonly level: 'error'\n  readonly error: unknown\n  readonly query: CompiledQuery\n  readonly queryDurationMillis: number\n}\n\nexport type LogEvent = QueryLogEvent | ErrorLogEvent\nexport type Logger = (event: LogEvent) => void | Promise<void>\nexport type LogConfig = ReadonlyArray<LogLevel> | Logger\n\nexport class Log {\n  readonly #levels: Readonly<Record<LogLevel, boolean>>\n  readonly #logger: Logger\n\n  constructor(config: LogConfig) {\n    if (isFunction(config)) {\n      this.#logger = config\n\n      this.#levels = freeze({\n        query: true,\n        error: true,\n      })\n    } else {\n      this.#logger = defaultLogger\n\n      this.#levels = freeze({\n        query: config.includes('query'),\n        error: config.includes('error'),\n      })\n    }\n  }\n\n  isLevelEnabled(level: LogLevel): boolean {\n    return this.#levels[level]\n  }\n\n  async query(getEvent: () => QueryLogEvent) {\n    if (this.#levels.query) {\n      await this.#logger(getEvent())\n    }\n  }\n\n  async error(getEvent: () => ErrorLogEvent) {\n    if (this.#levels.error) {\n      await this.#logger(getEvent())\n    }\n  }\n}\n\nfunction defaultLogger(event: LogEvent): void {\n  if (event.level === 'query') {\n    const prefix = `kysely:query:${event.isStream ? 'stream:' : ''}`\n    console.log(`${prefix} ${event.query.sql}`)\n    console.log(`${prefix} duration: ${event.queryDurationMillis.toFixed(1)}ms`)\n  } else if (event.level === 'error') {\n    if (event.error instanceof Error) {\n      console.error(`kysely:error: ${event.error.stack ?? event.error.message}`)\n    } else {\n      console.error(\n        `kysely:error: ${JSON.stringify({\n          error: event.error,\n          query: event.query.sql,\n          queryDurationMillis: event.queryDurationMillis,\n        })}`,\n      )\n    }\n  }\n}\n"
  },
  {
    "path": "src/util/object-utils.ts",
    "content": "import type { ShallowRecord } from './type-utils.js'\n\nexport function isEmpty(obj: ArrayLike<unknown> | string | object): boolean {\n  if (Array.isArray(obj) || isString(obj) || isBuffer(obj)) {\n    return obj.length === 0\n  } else if (obj) {\n    return Object.keys(obj).length === 0\n  }\n\n  return false\n}\n\nexport function isUndefined(obj: unknown): obj is undefined {\n  return typeof obj === 'undefined' || obj === undefined\n}\n\nexport function isString(obj: unknown): obj is string {\n  return typeof obj === 'string'\n}\n\nexport function isNumber(obj: unknown): obj is number {\n  return typeof obj === 'number'\n}\n\nexport function isBoolean(obj: unknown): obj is boolean {\n  return typeof obj === 'boolean'\n}\n\nexport function isNull(obj: unknown): obj is null {\n  return obj === null\n}\n\nexport function isDate(obj: unknown): obj is Date {\n  return obj instanceof Date\n}\n\nexport function isBigInt(obj: unknown): obj is bigint {\n  return typeof obj === 'bigint'\n}\n\n// Don't change the returnd type to `obj is Buffer` to not create a\n// hard dependency to node.\nexport function isBuffer(obj: unknown): obj is { length: number } {\n  return typeof Buffer !== 'undefined' && Buffer.isBuffer(obj)\n}\n\nexport function isFunction(obj: unknown): obj is Function {\n  return typeof obj === 'function'\n}\n\nexport function isObject(obj: unknown): obj is ShallowRecord<string, unknown> {\n  return typeof obj === 'object' && obj !== null\n}\n\nexport function isArrayBufferOrView(\n  obj: unknown,\n): obj is ArrayBuffer | ArrayBufferView {\n  return obj instanceof ArrayBuffer || ArrayBuffer.isView(obj)\n}\n\nexport function isPlainObject(obj: unknown): obj is Record<string, unknown> {\n  if (!isObject(obj) || getTag(obj) !== '[object Object]') {\n    return false\n  }\n\n  if (Object.getPrototypeOf(obj) === null) {\n    return true\n  }\n\n  let proto = obj\n  while (Object.getPrototypeOf(proto) !== null) {\n    proto = Object.getPrototypeOf(proto)\n  }\n\n  return Object.getPrototypeOf(obj) === proto\n}\n\nexport function getLast<T>(arr: ArrayLike<T>): T | undefined {\n  return arr[arr.length - 1]\n}\n\nexport function freeze<T>(obj: T): Readonly<T> {\n  return Object.freeze(obj)\n}\n\nexport function asArray<T>(arg: T | ReadonlyArray<T>): ReadonlyArray<T> {\n  if (isReadonlyArray(arg)) {\n    return arg\n  } else {\n    return [arg]\n  }\n}\n\nexport function asReadonlyArray<T>(\n  arg: T | ReadonlyArray<T>,\n): ReadonlyArray<T> {\n  if (isReadonlyArray(arg)) {\n    return arg\n  } else {\n    return freeze([arg])\n  }\n}\n\nexport function isReadonlyArray(arg: unknown): arg is ReadonlyArray<unknown> {\n  return Array.isArray(arg)\n}\n\nexport function noop<T>(obj: T): T {\n  return obj\n}\n\nexport function compare(obj1: unknown, obj2: unknown): boolean {\n  if (isReadonlyArray(obj1) && isReadonlyArray(obj2)) {\n    return compareArrays(obj1, obj2)\n  } else if (isObject(obj1) && isObject(obj2)) {\n    return compareObjects(obj1, obj2)\n  }\n\n  return obj1 === obj2\n}\n\nfunction compareArrays(\n  arr1: ReadonlyArray<unknown>,\n  arr2: ReadonlyArray<unknown>,\n): boolean {\n  if (arr1.length !== arr2.length) {\n    return false\n  }\n\n  for (let i = 0; i < arr1.length; ++i) {\n    if (!compare(arr1[i], arr2[i])) {\n      return false\n    }\n  }\n\n  return true\n}\n\nfunction compareObjects(\n  obj1: Record<string, unknown>,\n  obj2: Record<string, unknown>,\n): boolean {\n  if (isBuffer(obj1) && isBuffer(obj2)) {\n    return compareBuffers(obj1, obj2)\n  } else if (isDate(obj1) && isDate(obj2)) {\n    return compareDates(obj1, obj2)\n  }\n\n  return compareGenericObjects(obj1, obj2)\n}\n\nfunction compareBuffers(buf1: unknown, buf2: unknown): boolean {\n  return Buffer.compare(buf1 as any, buf2 as any) === 0\n}\n\nfunction compareDates(date1: Date, date2: Date) {\n  return date1.getTime() === date2.getTime()\n}\n\nfunction compareGenericObjects(\n  obj1: Record<string, unknown>,\n  obj2: Record<string, unknown>,\n): boolean {\n  const keys1 = Object.keys(obj1)\n  const keys2 = Object.keys(obj2)\n\n  if (keys1.length !== keys2.length) {\n    return false\n  }\n\n  for (const key of keys1) {\n    if (!compare(obj1[key], obj2[key])) {\n      return false\n    }\n  }\n\n  return true\n}\n\nconst toString = Object.prototype.toString\n\nfunction getTag(value: unknown): string {\n  if (value == null) {\n    return value === undefined ? '[object Undefined]' : '[object Null]'\n  }\n\n  return toString.call(value)\n}\n"
  },
  {
    "path": "src/util/performance-now.ts",
    "content": "import { isFunction } from './object-utils.js'\n\nexport function performanceNow() {\n  if (typeof performance !== 'undefined' && isFunction(performance.now)) {\n    return performance.now()\n  } else {\n    return Date.now()\n  }\n}\n"
  },
  {
    "path": "src/util/provide-controlled-connection.ts",
    "content": "import type { ConnectionProvider } from '../driver/connection-provider.js'\nimport type { DatabaseConnection } from '../driver/database-connection.js'\nimport { Deferred } from './deferred.js'\nimport { freeze } from './object-utils.js'\n\nexport interface ControlledConnection {\n  readonly connection: DatabaseConnection\n  readonly release: () => void\n}\n\nexport async function provideControlledConnection(\n  connectionProvider: ConnectionProvider,\n): Promise<ControlledConnection> {\n  const connectionDefer = new Deferred<DatabaseConnection>()\n  const connectionReleaseDefer = new Deferred<void>()\n\n  connectionProvider\n    .provideConnection(async (connection) => {\n      connectionDefer.resolve(connection)\n      return await connectionReleaseDefer.promise\n    })\n    .catch((ex) => connectionDefer.reject(ex))\n\n  // Create composite of the connection and the release method instead of\n  // modifying the connection or creating a new nesting `DatabaseConnection`.\n  // This way we don't accidentally override any methods of 3rd party\n  // connections and don't return wrapped connections to drivers that\n  // expect a certain specific connection class.\n  return freeze({\n    connection: await connectionDefer.promise,\n    release: connectionReleaseDefer.resolve,\n  })\n}\n"
  },
  {
    "path": "src/util/query-id.ts",
    "content": "import { randomString } from './random-string.js'\n\nexport interface QueryId {\n  readonly queryId: string\n}\n\nexport function createQueryId(): QueryId {\n  return new LazyQueryId()\n}\n\nclass LazyQueryId implements QueryId {\n  #queryId: string | undefined\n\n  get queryId(): string {\n    if (this.#queryId === undefined) {\n      this.#queryId = randomString(8)\n    }\n\n    return this.#queryId\n  }\n}\n"
  },
  {
    "path": "src/util/random-string.ts",
    "content": "const CHARS = [\n  'A',\n  'B',\n  'C',\n  'D',\n  'E',\n  'F',\n  'G',\n  'H',\n  'I',\n  'J',\n  'K',\n  'L',\n  'M',\n  'N',\n  'O',\n  'P',\n  'Q',\n  'R',\n  'S',\n  'T',\n  'U',\n  'V',\n  'W',\n  'X',\n  'Y',\n  'Z',\n  'a',\n  'b',\n  'c',\n  'd',\n  'e',\n  'f',\n  'g',\n  'h',\n  'i',\n  'j',\n  'k',\n  'l',\n  'm',\n  'n',\n  'o',\n  'p',\n  'q',\n  'r',\n  's',\n  't',\n  'u',\n  'v',\n  'w',\n  'x',\n  'y',\n  'z',\n  '0',\n  '1',\n  '2',\n  '3',\n  '4',\n  '5',\n  '6',\n  '7',\n  '8',\n  '9',\n]\n\nexport function randomString(length: number): string {\n  let chars = ''\n\n  for (let i = 0; i < length; ++i) {\n    chars += randomChar()\n  }\n\n  return chars\n}\n\nfunction randomChar() {\n  return CHARS[~~(Math.random() * CHARS.length)]\n}\n"
  },
  {
    "path": "src/util/require-all-props.ts",
    "content": "/**\n * Utility type to force use of all properties of T.\n *\n * Similar to Required<T> build-in type, but allows `undefined` values.\n */\ntype AllProps<T> = T & { [P in keyof T]-?: unknown }\n\n/**\n * Helper function to check listed properties according to given type. Check if all properties has been used when object is initialised.\n *\n * Example use:\n *\n * ```ts\n * type SomeType = { propA: string; propB?: number; }\n *\n * // propB has to be mentioned even it is optional. It still should be initialized with undefined.\n * const a: SomeType = requireAllProps<SomeType>({ propA: \"value A\", propB: undefined });\n *\n * // checked type is implicit for variable.\n * const b = requireAllProps<SomeType>({ propA: \"value A\", propB: undefined });\n * ```\n *\n * Wrong use of this helper:\n *\n * 1. Omit checked type - all checked properties will be expect as of type never\n *\n * ```ts\n * type SomeType = { propA: string; propB?: number; }\n * // const z: SomeType = requireAllProps({ propC: \"no type will work\" }); // Property 'propA' is missing in type '{ propC: string; }' but required in type 'SomeType'.\n * ```\n *\n * 2. Apply to spreaded object - there is no way how to check in compile time if spreaded object contains all properties\n *\n * ```ts\n * type SomeType = { propA: string; propB?: number; }\n * const y: SomeType = { propA: \"\" }; // valid object according to SomeType declaration\n * // const x = requireAllProps<SomeType>({ ...y }); // Argument of type '{ propA: string; propB?: number; }' is not assignable to parameter of type 'AllProps<SomeType>'.\n * ```\n *\n * @param obj object to check if all properties has been used\n * @returns untouched obj parameter is returned\n */\nexport function requireAllProps<T>(obj: AllProps<T>): T {\n  return obj\n}\n"
  },
  {
    "path": "src/util/stack-trace-utils.ts",
    "content": "import { isObject, isString } from './object-utils.js'\n\nexport function extendStackTrace(err: unknown, stackError: Error): unknown {\n  if (isStackHolder(err) && stackError.stack) {\n    // Remove the first line that just says `Error`.\n    const stackExtension = stackError.stack.split('\\n').slice(1).join('\\n')\n\n    err.stack += `\\n${stackExtension}`\n    return err\n  }\n\n  return err\n}\n\ninterface StackHolder {\n  stack: string\n}\n\nfunction isStackHolder(obj: unknown): obj is StackHolder {\n  return isObject(obj) && isString(obj.stack)\n}\n"
  },
  {
    "path": "src/util/streamable.ts",
    "content": "export interface Streamable<O> {\n  /**\n   * Executes the query and streams the rows.\n   *\n   * The optional argument `chunkSize` defines how many rows to fetch from the database\n   * at a time. It only affects some dialects like PostgreSQL that support it.\n   *\n   * ### Examples\n   *\n   * ```ts\n   * const stream = db\n   *   .selectFrom('person')\n   *   .select(['first_name', 'last_name'])\n   *   .where('gender', '=', 'other')\n   *   .stream()\n   *\n   * for await (const person of stream) {\n   *   console.log(person.first_name)\n   *\n   *   if (person.last_name === 'Something') {\n   *     // Breaking or returning before the stream has ended will release\n   *     // the database connection and invalidate the stream.\n   *     break\n   *   }\n   * }\n   * ```\n   */\n  stream(chunkSize?: number): AsyncIterableIterator<O>\n}\n"
  },
  {
    "path": "src/util/type-error.ts",
    "content": "export interface KyselyTypeError<E extends string> {\n  readonly __kyselyTypeError__: E\n}\n"
  },
  {
    "path": "src/util/type-utils.ts",
    "content": "import type { InsertResult } from '../query-builder/insert-result.js'\nimport type { DeleteResult } from '../query-builder/delete-result.js'\nimport type { UpdateResult } from '../query-builder/update-result.js'\nimport type { KyselyTypeError } from './type-error.js'\nimport type { MergeResult } from '../query-builder/merge-result.js'\n\n/**\n * Given a database type and a union of table names in that db, returns\n * a union type with all possible column names.\n *\n * Example:\n *\n * ```ts\n * interface Person {\n *   id: number\n * }\n *\n * interface Pet {\n *   name: string\n *   species: 'cat' | 'dog'\n * }\n *\n * interface Movie {\n *   stars: number\n * }\n *\n * interface Database {\n *   person: Person\n *   pet: Pet\n *   movie: Movie\n * }\n *\n * type Columns = AnyColumn<Database, 'person' | 'pet'>\n *\n * // Columns == 'id' | 'name' | 'species'\n * ```\n */\nexport type AnyColumn<DB, TB extends keyof DB> = {\n  [T in TB]: keyof DB[T]\n}[TB] &\n  string\n\n/**\n * Extracts a column type.\n */\nexport type ExtractColumnType<DB, TB extends keyof DB, C> = {\n  [T in TB]: C extends keyof DB[T] ? DB[T][C] : never\n}[TB]\n\n/**\n * Given a database type and a union of table names in that db, returns\n * a union type with all possible `table`.`column` combinations.\n *\n * Example:\n *\n * ```ts\n * interface Person {\n *   id: number\n * }\n *\n * interface Pet {\n *   name: string\n *   species: 'cat' | 'dog'\n * }\n *\n * interface Movie {\n *   stars: number\n * }\n *\n * interface Database {\n *   person: Person\n *   pet: Pet\n *   movie: Movie\n * }\n *\n * type Columns = AnyColumnWithTable<Database, 'person' | 'pet'>\n *\n * // Columns == 'person.id' | 'pet.name' | 'pet.species'\n * ```\n */\nexport type AnyColumnWithTable<DB, TB extends keyof DB> = {\n  [T in TB]: `${T & string}.${keyof DB[T] & string}`\n}[TB]\n\n/**\n * Just like {@link AnyColumn} but with a ` as <string>` suffix.\n */\nexport type AnyAliasedColumn<DB, TB extends keyof DB> = `${AnyColumn<\n  DB,\n  TB\n>} as ${string}`\n\n/**\n * Just like {@link AnyColumnWithTable} but with a ` as <string>` suffix.\n */\nexport type AnyAliasedColumnWithTable<\n  DB,\n  TB extends keyof DB,\n> = `${AnyColumnWithTable<DB, TB>} as ${string}`\n\n/**\n * Extracts the item type of an array.\n */\nexport type ArrayItemType<T> = T extends ReadonlyArray<infer I> ? I : never\n\nexport type SimplifySingleResult<O> = O extends InsertResult\n  ? O\n  : O extends DeleteResult\n    ? O\n    : O extends UpdateResult\n      ? O\n      : O extends MergeResult\n        ? O\n        : Simplify<O> | undefined\n\nexport type SimplifyResult<O> = O extends InsertResult\n  ? O\n  : O extends DeleteResult\n    ? O\n    : O extends UpdateResult\n      ? O\n      : O extends MergeResult\n        ? O\n        : Simplify<O>\n\nexport type Simplify<T> = DrainOuterGeneric<{ [K in keyof T]: T[K] } & {}>\n\n/**\n * Represents a database row whose column names and their types are unknown.\n */\nexport type UnknownRow = Record<string, unknown>\n\n/**\n * Makes all properties of object type `T` nullable.\n */\nexport type Nullable<T> = { [P in keyof T]: T[P] | null }\n\n/**\n * Evaluates to `true` if `T` is `never`.\n */\nexport type IsNever<T> = [T] extends [never] ? true : false\n\n/**\n * Evaluates to `true` if `T` is `any`.\n */\nexport type IsAny<T> = 0 extends T & 1 ? true : false\n\n/**\n * Evaluates to `true` if the types `T` and `U` are equal.\n */\nexport type Equals<T, U> =\n  (<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2\n    ? true\n    : false\n\nexport type NarrowPartial<O, T> = DrainOuterGeneric<\n  T extends object\n    ? {\n        [K in keyof O & string]: K extends keyof T\n          ? T[K] extends NotNull\n            ? Exclude<O[K], null>\n            : T[K] extends O[K]\n              ? T[K]\n              : KyselyTypeError<`$narrowType() call failed: passed type does not exist in '${K}'s type union`>\n          : O[K]\n      }\n    : never\n>\n\n/**\n * A type constant for marking a column as not null. Can be used with `$narrowPartial`.\n *\n * Example:\n *\n * ```ts\n * import type { NotNull } from 'kysely'\n *\n * await db.selectFrom('person')\n *   .where('nullable_column', 'is not', null)\n *   .selectAll()\n *   .$narrowType<{ nullable_column: NotNull }>()\n *   .executeTakeFirstOrThrow()\n * ```\n */\nexport type NotNull = { readonly __notNull__: unique symbol }\n\nexport type SqlBool = boolean | 0 | 1\n\n/**\n * Utility to reduce depth of TypeScript's internal type instantiation stack.\n *\n * Example:\n *\n * ```ts\n * type A<T> = { item: T }\n *\n * type Test<T> = A<\n *   A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<T>>>>>>>>>>>>>>>>>>>>>>>>\n * >\n *\n * // type Error = Test<number> // Type instantiation is excessively deep and possibly infinite.ts (2589)\n * ```\n *\n * To fix this, we can use `DrainOuterGeneric`:\n *\n * ```ts\n * type A<T> = DrainOuterGeneric<{ item: T }>\n *\n * type Test<T> = A<\n *  A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<T>>>>>>>>>>>>>>>>>>>>>>>>\n * >\n *\n * type Ok = Test<number> // Ok\n * ```\n */\nexport type DrainOuterGeneric<T> = [T] extends [unknown] ? T : never\n\nexport type ShallowRecord<K extends keyof any, T> = DrainOuterGeneric<{\n  [P in K]: T\n}>\n\n/**\n * Dehydrates any root properties of an object that are not valid JSON types.\n *\n * For now, we catch anything in {@link StringsWhenDataTypeNotAvailable} and convert it to `string`.\n */\nexport type ShallowDehydrateObject<O> = {\n  [K in keyof O]: ShallowDehydrateValue<O[K]>\n}\n\n/**\n * Dehydrates a value when it is not a valid JSON type.\n *\n * For now, we catch anything in {@link StringsWhenDataTypeNotAvailable} and convert it to `string`,\n * and anything in {@link NumbersWhenDataTypeNotAvailable} and convert it to `number`.\n */\nexport type ShallowDehydrateValue<T> = T extends null | undefined\n  ? T\n  : T extends (infer U)[] | null | undefined\n    ? Array<ShallowDehydrateValue<U>> | Extract<T, null | undefined>\n    :\n        | Exclude<\n            T,\n            StringsWhenDataTypeNotAvailable | NumbersWhenDataTypeNotAvailable\n          >\n        | ([Extract<T, NumbersWhenDataTypeNotAvailable>] extends [never]\n            ? never\n            : number)\n        | ([Extract<T, StringsWhenDataTypeNotAvailable>] extends [never]\n            ? never\n            : string)\n\nexport type StringsWhenDataTypeNotAvailable =\n  | Date\n  // Many Node.js drivers return `Buffer` by default for some column data types.\n  // Buffer is a subclass of `Uint8Array`. `Buffer` doesn't exist in non-Node TypeScript\n  // environments - and results in `any` or a compilation error if used.\n  | Uint8Array\n\nexport type NumbersWhenDataTypeNotAvailable = bigint | NumericString\n\nexport type NumericString = `${number}`\n"
  },
  {
    "path": "test/browser/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Kysely browser test</title>\n    <script src=\"bundle.js\"></script>\n  </head>\n  <body></body>\n</html>\n"
  },
  {
    "path": "test/browser/main.ts",
    "content": "import {\n  Kysely,\n  Generated,\n  DummyDriver,\n  SqliteAdapter,\n  SqliteIntrospector,\n  SqliteQueryCompiler,\n} from '../..'\n\ninterface Person {\n  id: Generated<number>\n  first_name: string\n  last_name: string | null\n}\n\ninterface Database {\n  person: Person\n}\n\nconst db = new Kysely<Database>({\n  dialect: {\n    createAdapter() {\n      return new SqliteAdapter()\n    },\n    createDriver() {\n      return new DummyDriver()\n    },\n    createIntrospector(db: Kysely<any>) {\n      return new SqliteIntrospector(db)\n    },\n    createQueryCompiler() {\n      return new SqliteQueryCompiler()\n    },\n  },\n})\n\nwindow.addEventListener('load', () => {\n  const sql = db.selectFrom('person').select('id').compile()\n\n  const result = document.createElement('span')\n  result.id = 'result'\n  result.innerHTML = sql.sql\n\n  document.body.appendChild(result)\n})\n"
  },
  {
    "path": "test/browser/test.js",
    "content": "/**\n * Super simple smoke test that just opens an empty web page\n * and runs the `main.ts` script in it (bundled with esbuild).\n * The script builds a query and writes the result to a span\n * in the browser.\n */\n\nconst path = require('path')\nconst { chromium } = require('playwright')\n\nconst EXPECTED_SQL = 'select \"id\" from \"person\"'\n\n;(async () => {\n  let browser\n\n  try {\n    browser = await chromium.launch({ headless: true })\n    const page = await browser.newPage()\n\n    await page.goto('file://' + path.join(__dirname, 'index.html'))\n    // Wait until the main.ts script has finished and the result\n    // span exists in the body.\n    await page.waitForSelector('#result', { timeout: 5000 })\n    const sql = await page.$eval('#result', (el) => el.innerHTML)\n\n    if (sql !== EXPECTED_SQL) {\n      throw new Error(`failed to build a query`)\n    }\n  } catch (error) {\n    console.error(error)\n    process.exit(1)\n  } finally {\n    await browser?.close()\n  }\n\n  console.log('browser test passed')\n})()\n"
  },
  {
    "path": "test/bun/bun.test.ts",
    "content": "import { createPool } from 'mysql2'\nimport { Pool } from 'pg'\nimport * as Tarn from 'tarn'\nimport * as Tedious from 'tedious'\nimport {\n  Generated,\n  Kysely,\n  PostgresDialect,\n  MysqlDialect,\n  sql,\n  MssqlDialect,\n} from '../../dist/esm/index.js'\n\ninterface Person {\n  id: Generated<number>\n  first_name: string\n  last_name: string | null\n}\n\ninterface Database {\n  person: Person\n}\n\nconst dbs = [\n  new Kysely<Database>({\n    dialect: new PostgresDialect({\n      pool: new Pool({\n        database: 'kysely_test',\n        host: 'localhost',\n        user: 'kysely',\n        port: 5434,\n      }),\n    }),\n  }),\n  new Kysely<Database>({\n    dialect: new MysqlDialect({\n      pool: createPool({\n        database: 'kysely_test',\n        host: 'localhost',\n        user: 'kysely',\n        password: 'kysely',\n        port: 3308,\n      }),\n    }),\n  }),\n  new Kysely<Database>({\n    dialect: new MssqlDialect({\n      tarn: {\n        ...Tarn,\n        options: {\n          min: 0,\n          max: 10,\n        },\n      },\n      tedious: {\n        ...Tedious,\n        connectionFactory: () =>\n          new Tedious.Connection({\n            authentication: {\n              options: {\n                password: 'KyselyTest0',\n                userName: 'sa',\n              },\n              type: 'default',\n            },\n            options: {\n              connectTimeout: 3000,\n              database: 'kysely_test',\n              encrypt: false,\n              port: 21433,\n              trustServerCertificate: true,\n            },\n            server: 'localhost',\n          }),\n      },\n    }),\n  }),\n]\n\nif (\n  dbs\n    .map((db) => db.selectFrom('person').select('id').compile().sql)\n    .some(\n      (sql) => sql.match(/^select [\"`]id[\"`] from [\"`]person[\"`]$/) === null,\n    )\n) {\n  console.error('bun test failed')\n  process.exit(1)\n}\n\nconst query = sql`select 1`\n\nawait Promise.all(dbs.map((db) => query.execute(db)))\n\nconsole.log('bun test passed')\n\nawait Promise.all(dbs.map((db) => db.destroy()))\n\nprocess.exit(0) // hangs otherwise...\n"
  },
  {
    "path": "test/bun/package.json",
    "content": "{\n  \"name\": \"kysely-bun-test\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"bun bun.test.ts\"\n  },\n  \"dependencies\": {\n    \"kysely\": \"link:kysely\",\n    \"mysql2\": \"^3.20.0\",\n    \"pg\": \"^8.20.0\",\n    \"tarn\": \"^3.0.2\",\n    \"tedious\": \"^19.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/bun\": \"^1.3.11\",\n    \"typescript\": \"^5.9.3\"\n  }\n}\n"
  },
  {
    "path": "test/bun/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Node\",\n    \"allowSyntheticDefaultImports\": true,\n    \"esModuleInterop\": true,\n    \"strict\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"types\": [\"bun\"]\n  }\n}\n"
  },
  {
    "path": "test/cloudflare-workers/.dev.vars",
    "content": ""
  },
  {
    "path": "test/cloudflare-workers/api.ts",
    "content": "import { Pool } from 'pg'\nimport { Hono } from 'hono'\nimport { Generated, Kysely, PostgresDialect, sql } from '../../'\n\ninterface Person {\n  id: Generated<number>\n  first_name: string\n  last_name: string | null\n}\n\ninterface Database {\n  person: Person\n}\n\nconst db = new Kysely<Database>({\n  dialect: new PostgresDialect({\n    pool: new Pool({\n      database: 'kysely_test',\n      host: 'localhost',\n      user: 'kysely',\n      port: 5434,\n    }),\n  }),\n})\n\nconst app = new Hono()\n\napp.get('/', async (c) => {\n  if (\n    db.selectFrom('person').selectAll().compile().sql !==\n    'select * from \"person\"'\n  ) {\n    throw new Error('Unexpected SQL')\n  }\n\n  await sql`select 1 as ok`.execute(db)\n\n  return c.body(null)\n})\n\nexport default app\n"
  },
  {
    "path": "test/cloudflare-workers/package.json",
    "content": "{\n  \"name\": \"kysely-cloudflare-workers-test\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"node --experimental-strip-types test.ts\"\n  },\n  \"dependencies\": {\n    \"hono\": \"^4.12.8\"\n  },\n  \"devDependencies\": {\n    \"wrangler\": \"^4.75.0\"\n  }\n}\n"
  },
  {
    "path": "test/cloudflare-workers/test.ts",
    "content": "import { unstable_dev } from 'wrangler'\n;(async () => {\n  const worker = await unstable_dev('./api.ts', {\n    compatibilityDate: '2025-07-29',\n    compatibilityFlags: ['nodejs_compat'],\n    local: true,\n  })\n\n  let exitCode = 0\n\n  try {\n    const response = await worker.fetch('http://example.com')\n\n    if (!response.ok) {\n      throw new Error(`Unexpected response: ${response.status}`)\n    }\n\n    console.log('test successful!')\n  } catch (error) {\n    exitCode = 1\n  } finally {\n    await worker.stop()\n    process.exit(exitCode)\n  }\n})()\n"
  },
  {
    "path": "test/composite-ts/index.mts",
    "content": "import type { Kysely } from 'kysely'\n\ninterface DB {\n  MyTable: {\n    myColumn: string\n    anotherColumn: number\n  }\n}\n\nexport function foo<T extends 'myColumn'>(db: Kysely<DB>, field: T) {\n  return db\n    .selectFrom('MyTable')\n    .select(field) // <------- was missing DrainOuterGeneric & ExtractColumnType\n    .$narrowType<{}>() // <------- was missing KyselyTypeError\n    .executeTakeFirst() // <------- was missing SimplifySingleResult\n}\n\nexport function bar<T extends keyof DB['MyTable']>(\n  db: Kysely<DB>,\n  columns: T[],\n) {\n  return db\n    .insertInto('MyTable')\n    .values({ myColumn: 'test', anotherColumn: 1 })\n    .returning(columns) // <----- was missing SimplifyResult\n    .execute()\n}\n\nexport function fizz(db: Kysely<DB>) {\n  return db.with(\n    // <----- was missing QueryCreatorWithCommonTableExpression\n    'cte',\n    (db) => db.selectFrom('MyTable').selectAll(),\n  )\n}\n"
  },
  {
    "path": "test/composite-ts/package.json",
    "content": "{\n  \"type\": \"module\",\n  \"scripts\": {\n    \"precheck:types\": \"cd ../.. && pnpm build && cp -r dist test/composite-ts/node_modules/kysely/\",\n    \"check:types\": \"tsc --noEmit\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5.9.3\"\n  },\n  \"dependencies\": {\n    \"kysely\": \"^0.28.9\"\n  }\n}\n"
  },
  {
    "path": "test/composite-ts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"nodenext\",\n    \"moduleResolution\": \"nodenext\",\n    \"composite\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"emitDeclarationOnly\": true,\n    \"outDir\": \"dist\",\n    \"isolatedModules\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true\n  },\n  \"exclude\": [\"node_modules\", \"dist\"],\n  \"include\": [\"*.mts\"]\n}\n"
  },
  {
    "path": "test/deno/cdn.test.ts",
    "content": "import { Generated, Kysely, MysqlDialect, PostgresDialect, sql } from 'kysely'\nimport { createPool } from 'mysql2'\nimport Pool from 'pg-pool'\n\ninterface Person {\n  id: Generated<number>\n  first_name: string\n  last_name: string | null\n}\n\ninterface Database {\n  person: Person\n}\n\nconst dbs = [\n  new Kysely<Database>({\n    dialect: new PostgresDialect({\n      pool: new Pool({\n        database: 'kysely_test',\n        host: 'localhost',\n        user: 'kysely',\n        port: 5434,\n      }),\n    }),\n  }),\n  new Kysely<Database>({\n    dialect: new MysqlDialect({\n      pool: createPool({\n        database: 'kysely_test',\n        host: 'localhost',\n        user: 'kysely',\n        password: 'kysely',\n        port: 3308,\n      }),\n    }),\n  }),\n]\n\nif (\n  dbs\n    .map((db) => db.selectFrom('person').select('id').compile().sql)\n    .some((sql) => sql.match(/^select [\"`]id[\"`] from [\"`]person[\"`]$/) == null)\n) {\n  console.error('CDN deno test failed')\n  Deno.exit(1)\n}\n\nconst query = sql`select 1`\n\nawait Promise.all(dbs.map((db) => query.execute(db)))\n\nconsole.error('CDN deno test passed')\n\nawait Promise.all(dbs.map((db) => db.destroy()))\n"
  },
  {
    "path": "test/deno/deno.json",
    "content": "{\n  \"imports\": {\n    \"kysely\": \"npm:kysely@^0.28.13\",\n    \"mysql2\": \"npm:mysql2@^3.20.0\",\n    \"pg\": \"npm:pg@^8.20.0\",\n    \"pg-pool\": \"npm:pg-pool@^3.13.0\"\n  }\n}\n"
  },
  {
    "path": "test/deno/local.test.ts",
    "content": "import {\n  Generated,\n  Kysely,\n  PostgresDialect,\n  MysqlDialect,\n  sql,\n} from '../../dist/esm/index.js'\nimport { createPool } from 'mysql2'\nimport Pool from 'pg-pool'\n\ninterface Person {\n  id: Generated<number>\n  first_name: string\n  last_name: string | null\n}\n\ninterface Database {\n  person: Person\n}\n\nconst dbs = [\n  new Kysely<Database>({\n    dialect: new PostgresDialect({\n      pool: new Pool({\n        database: 'kysely_test',\n        host: 'localhost',\n        user: 'kysely',\n        port: 5434,\n      }),\n    }),\n  }),\n  new Kysely<Database>({\n    dialect: new MysqlDialect({\n      pool: createPool({\n        database: 'kysely_test',\n        host: 'localhost',\n        user: 'kysely',\n        password: 'kysely',\n        port: 3308,\n      }),\n    }),\n  }),\n]\n\nif (\n  dbs\n    .map((db) => db.selectFrom('person').select('id').compile().sql)\n    .some((sql) => sql.match(/^select [\"`]id[\"`] from [\"`]person[\"`]$/) == null)\n) {\n  console.error('CDN deno test failed')\n  Deno.exit(1)\n}\n\nconst query = sql`select 1`\n\nawait Promise.all(dbs.map((db) => query.execute(db)))\n\nconsole.error('local deno test passed')\n\nawait Promise.all(dbs.map((db) => db.destroy()))\n"
  },
  {
    "path": "test/node/src/aggregate-function.test.ts",
    "content": "import {\n  AggregateFunctionBuilder,\n  ExpressionBuilder,\n  SimpleReferenceExpression,\n  ReferenceExpression,\n  sql,\n  expressionBuilder,\n} from '../../../'\nimport {\n  Database,\n  destroyTest,\n  initTest,\n  NOT_SUPPORTED,\n  TestContext,\n  testSql,\n  DIALECTS,\n} from './test-setup.js'\n\nconst funcNames = ['avg', 'count', 'max', 'min', 'sum'] as const\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: aggregate functions`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    for (const funcName of funcNames) {\n      describe(funcName, () => {\n        let func: ReturnType<typeof getAggregateFunctionFromTestContext>\n\n        before(() => {\n          func = getAggregateFunctionFromTestContext(ctx, funcName)\n        })\n\n        it(`should execute a query with ${funcName}(column) in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .select([\n              func('id').as(funcName),\n              (eb) =>\n                getAggregateFunctionFromExpressionBuilder(\n                  eb,\n                  funcName,\n                )('person.id').as(`another_${funcName}`),\n            ])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select ${funcName}(\"id\") as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select ${funcName}(\\`id\\`) as \\`${funcName}\\`,`,\n                `${funcName}(\\`person\\`.\\`id\\`) as \\`another_${funcName}\\``,\n                `from \\`person\\``,\n              ],\n              parameters: [],\n            },\n            mssql: {\n              sql: [\n                `select ${funcName}(\"id\") as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            sqlite: {\n              sql: [\n                `select ${funcName}(\"id\") as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(distinct column) in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .select([\n              func('id').distinct().as(funcName),\n              (eb) =>\n                getAggregateFunctionFromExpressionBuilder(\n                  eb,\n                  funcName,\n                )('person.id')\n                  .distinct()\n                  .as(`another_${funcName}`),\n            ])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select ${funcName}(distinct \"id\") as \"${funcName}\",`,\n                `${funcName}(distinct \"person\".\"id\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select ${funcName}(distinct \\`id\\`) as \\`${funcName}\\`,`,\n                `${funcName}(distinct \\`person\\`.\\`id\\`) as \\`another_${funcName}\\``,\n                `from \\`person\\``,\n              ],\n              parameters: [],\n            },\n            mssql: {\n              sql: [\n                `select ${funcName}(distinct \"id\") as \"${funcName}\",`,\n                `${funcName}(distinct \"person\".\"id\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            sqlite: {\n              sql: [\n                `select ${funcName}(distinct \"id\") as \"${funcName}\",`,\n                `${funcName}(distinct \"person\".\"id\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(column) over() in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .select([\n              func('id').over().as(funcName),\n              (eb) =>\n                getAggregateFunctionFromExpressionBuilder(\n                  eb,\n                  funcName,\n                )('person.id')\n                  .over()\n                  .as(`another_${funcName}`),\n            ])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select ${funcName}(\"id\") over() as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\") over() as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select ${funcName}(\\`id\\`) over() as \\`${funcName}\\`,`,\n                `${funcName}(\\`person\\`.\\`id\\`) over() as \\`another_${funcName}\\``,\n                `from \\`person\\``,\n              ],\n              parameters: [],\n            },\n            mssql: {\n              sql: [\n                `select ${funcName}(\"id\") over() as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\") over() as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            sqlite: {\n              sql: [\n                `select ${funcName}(\"id\") over() as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\") over() as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(column) over(partition by column) in select clause`, async () => {\n          const query = ctx.db.selectFrom('person').select([\n            func('id')\n              .over((ob) => ob.partitionBy(['first_name']))\n              .as(funcName),\n            (eb) =>\n              getAggregateFunctionFromExpressionBuilder(\n                eb,\n                funcName,\n              )('person.id')\n                .over((ob) => ob.partitionBy('person.first_name'))\n                .as(`another_${funcName}`),\n          ])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select ${funcName}(\"id\")`,\n                `over(partition by \"first_name\") as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\")`,\n                `over(partition by \"person\".\"first_name\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select ${funcName}(\\`id\\`)`,\n                `over(partition by \\`first_name\\`) as \\`${funcName}\\`,`,\n                `${funcName}(\\`person\\`.\\`id\\`)`,\n                `over(partition by \\`person\\`.\\`first_name\\`) as \\`another_${funcName}\\``,\n                `from \\`person\\``,\n              ],\n              parameters: [],\n            },\n            mssql: {\n              sql: [\n                `select ${funcName}(\"id\")`,\n                `over(partition by \"first_name\") as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\")`,\n                `over(partition by \"person\".\"first_name\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            sqlite: {\n              sql: [\n                `select ${funcName}(\"id\")`,\n                `over(partition by \"first_name\") as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\")`,\n                `over(partition by \"person\".\"first_name\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(column) over(order by column asc/desc) in select clause`, async () => {\n          const query = ctx.db.selectFrom('person').select([\n            func('id')\n              .over((ob) =>\n                ob.orderBy('last_name', 'asc').orderBy('first_name', 'asc'),\n              )\n              .as(funcName),\n            (eb) =>\n              getAggregateFunctionFromExpressionBuilder(\n                eb,\n                funcName,\n              )('person.id')\n                .over((ob) =>\n                  ob\n                    .orderBy('person.last_name', 'desc')\n                    .orderBy('person.first_name', 'desc'),\n                )\n                .as(`another_${funcName}`),\n          ])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select ${funcName}(\"id\")`,\n                `over(order by \"last_name\" asc,`,\n                `\"first_name\" asc) as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\")`,\n                `over(order by \"person\".\"last_name\" desc,`,\n                `\"person\".\"first_name\" desc) as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select ${funcName}(\\`id\\`)`,\n                `over(order by \\`last_name\\` asc,`,\n                `\\`first_name\\` asc) as \\`${funcName}\\`,`,\n                `${funcName}(\\`person\\`.\\`id\\`)`,\n                `over(order by \\`person\\`.\\`last_name\\` desc,`,\n                `\\`person\\`.\\`first_name\\` desc) as \\`another_${funcName}\\``,\n                `from \\`person\\``,\n              ],\n              parameters: [],\n            },\n            mssql: {\n              sql: [\n                `select ${funcName}(\"id\")`,\n                `over(order by \"last_name\" asc,`,\n                `\"first_name\" asc) as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\")`,\n                `over(order by \"person\".\"last_name\" desc,`,\n                `\"person\".\"first_name\" desc) as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            sqlite: {\n              sql: [\n                `select ${funcName}(\"id\")`,\n                `over(order by \"last_name\" asc,`,\n                `\"first_name\" asc) as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\")`,\n                `over(order by \"person\".\"last_name\" desc,`,\n                `\"person\".\"first_name\" desc) as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(column) over(partition by column order by column asc/desc) in select clause`, async () => {\n          const query = ctx.db.selectFrom('person').select([\n            func('id')\n              .over((ob) =>\n                ob\n                  .partitionBy(['gender'])\n                  .orderBy('last_name', 'asc')\n                  .orderBy('first_name', 'asc'),\n              )\n              .as(funcName),\n            (eb) =>\n              getAggregateFunctionFromExpressionBuilder(\n                eb,\n                funcName,\n              )('person.id')\n                .over((ob) =>\n                  ob\n                    .partitionBy('person.gender')\n                    .orderBy('person.last_name', 'desc')\n                    .orderBy('person.first_name', 'desc'),\n                )\n                .as(`another_${funcName}`),\n          ])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select ${funcName}(\"id\")`,\n                `over(partition by \"gender\"`,\n                `order by \"last_name\" asc,`,\n                `\"first_name\" asc) as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\")`,\n                `over(partition by \"person\".\"gender\"`,\n                `order by \"person\".\"last_name\" desc,`,\n                `\"person\".\"first_name\" desc) as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select ${funcName}(\\`id\\`)`,\n                `over(partition by \\`gender\\``,\n                `order by \\`last_name\\` asc,`,\n                `\\`first_name\\` asc) as \\`${funcName}\\`,`,\n                `${funcName}(\\`person\\`.\\`id\\`)`,\n                `over(partition by \\`person\\`.\\`gender\\``,\n                `order by \\`person\\`.\\`last_name\\` desc,`,\n                `\\`person\\`.\\`first_name\\` desc) as \\`another_${funcName}\\``,\n                `from \\`person\\``,\n              ],\n              parameters: [],\n            },\n            mssql: {\n              sql: [\n                `select ${funcName}(\"id\")`,\n                `over(partition by \"gender\"`,\n                `order by \"last_name\" asc,`,\n                `\"first_name\" asc) as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\")`,\n                `over(partition by \"person\".\"gender\"`,\n                `order by \"person\".\"last_name\" desc,`,\n                `\"person\".\"first_name\" desc) as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            sqlite: {\n              sql: [\n                `select ${funcName}(\"id\")`,\n                `over(partition by \"gender\"`,\n                `order by \"last_name\" asc,`,\n                `\"first_name\" asc) as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\")`,\n                `over(partition by \"person\".\"gender\"`,\n                `order by \"person\".\"last_name\" desc,`,\n                `\"person\".\"first_name\" desc) as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(column) in having clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .select(['person.children'])\n            .groupBy(['person.children'])\n            .having(func('person.children'), '>=', 3)\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `having ${funcName}(\"person\".\"children\") >= $1`,\n              ],\n              parameters: [3],\n            },\n            mysql: {\n              sql: [\n                `select \\`person\\`.\\`children\\``,\n                `from \\`person\\``,\n                `group by \\`person\\`.\\`children\\``,\n                `having ${funcName}(\\`person\\`.\\`children\\`) >= ?`,\n              ],\n              parameters: [3],\n            },\n            mssql: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `having ${funcName}(\"person\".\"children\") >= @1`,\n              ],\n              parameters: [3],\n            },\n            sqlite: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `having ${funcName}(\"person\".\"children\") >= ?`,\n              ],\n              parameters: [3],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(column) in order by clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .select(['person.children'])\n            .groupBy(['person.children'])\n            .orderBy(func('person.children'), 'desc')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `order by ${funcName}(\"person\".\"children\") desc`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select \\`person\\`.\\`children\\``,\n                `from \\`person\\``,\n                `group by \\`person\\`.\\`children\\``,\n                `order by ${funcName}(\\`person\\`.\\`children\\`) desc`,\n              ],\n              parameters: [],\n            },\n            mssql: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `order by ${funcName}(\"person\".\"children\") desc`,\n              ],\n              parameters: [],\n            },\n            sqlite: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `order by ${funcName}(\"person\".\"children\") desc`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(column) and a dynamic reference in select clause`, async () => {\n          const dynamicReference = ctx.db.dynamic.ref('person.id')\n\n          const query = ctx.db\n            .selectFrom('person')\n            .select([\n              func(dynamicReference).as(funcName),\n              (eb) =>\n                getAggregateFunctionFromExpressionBuilder(\n                  eb,\n                  funcName,\n                )(dynamicReference).as(`another_${funcName}`),\n            ])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select ${funcName}(\"person\".\"id\") as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select ${funcName}(\\`person\\`.\\`id\\`) as \\`${funcName}\\`,`,\n                `${funcName}(\\`person\\`.\\`id\\`) as \\`another_${funcName}\\``,\n                `from \\`person\\``,\n              ],\n              parameters: [],\n            },\n            mssql: {\n              sql: [\n                `select ${funcName}(\"person\".\"id\") as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            sqlite: {\n              sql: [\n                `select ${funcName}(\"person\".\"id\") as \"${funcName}\",`,\n                `${funcName}(\"person\".\"id\") as \"another_${funcName}\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(column) and a dynamic reference in having clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .select(['person.children'])\n            .groupBy(['person.children'])\n            .having(func(ctx.db.dynamic.ref('person.children')), '>=', 3)\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `having ${funcName}(\"person\".\"children\") >= $1`,\n              ],\n              parameters: [3],\n            },\n            mysql: {\n              sql: [\n                `select \\`person\\`.\\`children\\``,\n                `from \\`person\\``,\n                `group by \\`person\\`.\\`children\\``,\n                `having ${funcName}(\\`person\\`.\\`children\\`) >= ?`,\n              ],\n              parameters: [3],\n            },\n            mssql: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `having ${funcName}(\"person\".\"children\") >= @1`,\n              ],\n              parameters: [3],\n            },\n            sqlite: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `having ${funcName}(\"person\".\"children\") >= ?`,\n              ],\n              parameters: [3],\n            },\n          })\n\n          await query.execute()\n        })\n\n        it(`should execute a query with ${funcName}(column) and a dynamic reference in order by clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .select(['person.children'])\n            .groupBy(['person.children'])\n            .orderBy(func(ctx.db.dynamic.ref('person.children')), 'desc')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `order by ${funcName}(\"person\".\"children\") desc`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select \\`person\\`.\\`children\\``,\n                `from \\`person\\``,\n                `group by \\`person\\`.\\`children\\``,\n                `order by ${funcName}(\\`person\\`.\\`children\\`) desc`,\n              ],\n              parameters: [],\n            },\n            mssql: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `order by ${funcName}(\"person\".\"children\") desc`,\n              ],\n              parameters: [],\n            },\n            sqlite: {\n              sql: [\n                `select \"person\".\"children\"`,\n                `from \"person\"`,\n                `group by \"person\".\"children\"`,\n                `order by ${funcName}(\"person\".\"children\") desc`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n\n        if (dialect === 'postgres' || dialect === 'sqlite') {\n          it(`should execute a query with ${funcName}(column) filter(where ...) in select clause`, async () => {\n            const query = ctx.db\n              .selectFrom('person')\n              .select([\n                func('person.id')\n                  .filterWhere('person.gender', '=', 'female')\n                  .as(funcName),\n                (eb) =>\n                  getAggregateFunctionFromExpressionBuilder(\n                    eb,\n                    funcName,\n                  )('person.id')\n                    .filterWhere('person.gender', '=', 'female')\n                    .as(`another_${funcName}`),\n              ])\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: [\n                  `select ${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = $1) as \"${funcName}\",`,\n                  `${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = $2) as \"another_${funcName}\"`,\n                  `from \"person\"`,\n                ],\n                parameters: ['female', 'female'],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: {\n                sql: [\n                  `select ${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = ?) as \"${funcName}\",`,\n                  `${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = ?) as \"another_${funcName}\"`,\n                  `from \"person\"`,\n                ],\n                parameters: ['female', 'female'],\n              },\n            })\n\n            await query.execute()\n          })\n\n          it(`should execute a query with ${funcName}(column) filter(where ... and ...) in select clause`, async () => {\n            const query = ctx.db\n              .selectFrom('person')\n              .select([\n                func('person.id')\n                  .filterWhere('person.gender', '=', 'female')\n                  .filterWhere('person.middle_name', 'is not', null)\n                  .as(funcName),\n                (eb) =>\n                  getAggregateFunctionFromExpressionBuilder(\n                    eb,\n                    funcName,\n                  )('person.id')\n                    .filterWhere('person.gender', '=', 'female')\n                    .filterWhere('person.middle_name', 'is not', null)\n                    .as(`another_${funcName}`),\n              ])\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: [\n                  `select ${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = $1`,\n                  `and \"person\".\"middle_name\" is not null) as \"${funcName}\",`,\n                  `${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = $2`,\n                  `and \"person\".\"middle_name\" is not null) as \"another_${funcName}\"`,\n                  `from \"person\"`,\n                ],\n                parameters: ['female', 'female'],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: {\n                sql: [\n                  `select ${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = ?`,\n                  `and \"person\".\"middle_name\" is not null) as \"${funcName}\",`,\n                  `${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = ?`,\n                  `and \"person\".\"middle_name\" is not null) as \"another_${funcName}\"`,\n                  `from \"person\"`,\n                ],\n                parameters: ['female', 'female'],\n              },\n            })\n\n            await query.execute()\n          })\n\n          it(`should execute a query with ${funcName}(column) filter(where ... or ...) in select clause`, async () => {\n            const query = ctx.db.selectFrom('person').select([\n              func('person.id')\n                .filterWhere(({ or, eb }) =>\n                  or([\n                    eb('person.gender', '=', 'female'),\n                    eb('person.middle_name', 'is not', null),\n                  ]),\n                )\n                .as(funcName),\n              (eb) =>\n                getAggregateFunctionFromExpressionBuilder(\n                  eb,\n                  funcName,\n                )('person.id')\n                  .filterWhere((eb) =>\n                    eb.or([\n                      eb('person.gender', '=', 'female'),\n                      eb('person.middle_name', 'is not', null),\n                    ]),\n                  )\n                  .as(`another_${funcName}`),\n            ])\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: [\n                  `select ${funcName}(\"person\".\"id\")`,\n                  `filter(where (\"person\".\"gender\" = $1`,\n                  `or \"person\".\"middle_name\" is not null)) as \"${funcName}\",`,\n                  `${funcName}(\"person\".\"id\")`,\n                  `filter(where (\"person\".\"gender\" = $2`,\n                  `or \"person\".\"middle_name\" is not null)) as \"another_${funcName}\"`,\n                  `from \"person\"`,\n                ],\n                parameters: ['female', 'female'],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: {\n                sql: [\n                  `select ${funcName}(\"person\".\"id\")`,\n                  `filter(where (\"person\".\"gender\" = ?`,\n                  `or \"person\".\"middle_name\" is not null)) as \"${funcName}\",`,\n                  `${funcName}(\"person\".\"id\")`,\n                  `filter(where (\"person\".\"gender\" = ?`,\n                  `or \"person\".\"middle_name\" is not null)) as \"another_${funcName}\"`,\n                  `from \"person\"`,\n                ],\n                parameters: ['female', 'female'],\n              },\n            })\n\n            await query.execute()\n          })\n\n          it(`should execute a query with ${funcName}(column) filter(where ...) over() in select clause`, async () => {\n            const query = ctx.db\n              .selectFrom('person')\n              .select([\n                func('person.id')\n                  .filterWhere('person.gender', '=', 'female')\n                  .over()\n                  .as(funcName),\n                (eb) =>\n                  getAggregateFunctionFromExpressionBuilder(\n                    eb,\n                    funcName,\n                  )('person.id')\n                    .filterWhere('person.gender', '=', 'female')\n                    .over()\n                    .as(`another_${funcName}`),\n              ])\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: [\n                  `select ${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = $1)`,\n                  `over() as \"${funcName}\",`,\n                  `${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = $2)`,\n                  `over() as \"another_${funcName}\"`,\n                  `from \"person\"`,\n                ],\n                parameters: ['female', 'female'],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: {\n                sql: [\n                  `select ${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = ?)`,\n                  `over() as \"${funcName}\",`,\n                  `${funcName}(\"person\".\"id\")`,\n                  `filter(where \"person\".\"gender\" = ?)`,\n                  `over() as \"another_${funcName}\"`,\n                  `from \"person\"`,\n                ],\n                parameters: ['female', 'female'],\n              },\n            })\n\n            await query.execute()\n          })\n        }\n\n        if (funcName === 'count') {\n          it(`should execute a query with ${funcName}(*) in select clause`, async () => {\n            const query = ctx.db\n              .selectFrom('person')\n              .select([\n                ctx.db.fn[`${funcName}All`]().as(funcName),\n                (eb) => eb.fn[`${funcName}All`]().as(`another_${funcName}`),\n              ])\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: [\n                  `select ${funcName}(*) as \"${funcName}\",`,\n                  `${funcName}(*) as \"another_${funcName}\"`,\n                  'from \"person\"',\n                ],\n                parameters: [],\n              },\n              mysql: {\n                sql: [\n                  `select ${funcName}(*) as \\`${funcName}\\`,`,\n                  `${funcName}(*) as \\`another_${funcName}\\``,\n                  'from `person`',\n                ],\n                parameters: [],\n              },\n              mssql: {\n                sql: [\n                  `select ${funcName}(*) as \"${funcName}\",`,\n                  `${funcName}(*) as \"another_${funcName}\"`,\n                  'from \"person\"',\n                ],\n                parameters: [],\n              },\n              sqlite: {\n                sql: [\n                  `select ${funcName}(*) as \"${funcName}\",`,\n                  `${funcName}(*) as \"another_${funcName}\"`,\n                  'from \"person\"',\n                ],\n                parameters: [],\n              },\n            })\n\n            await query.execute()\n          })\n\n          if (dialect === 'postgres') {\n            it(`should execute a query with ${funcName}(table.*) in select clause`, async () => {\n              const query = ctx.db\n                .selectFrom('person')\n                .innerJoin('pet', 'pet.owner_id', 'person.id')\n                .select([\n                  ctx.db.fn[`${funcName}All`]('person').as(funcName),\n                  (eb) =>\n                    eb.fn[`${funcName}All`]('person').as(`another_${funcName}`),\n                ])\n\n              testSql(query, dialect, {\n                postgres: {\n                  sql: [\n                    `select ${funcName}(\"person\".*) as \"${funcName}\",`,\n                    `${funcName}(\"person\".*) as \"another_${funcName}\"`,\n                    'from \"person\"',\n                    'inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"',\n                  ],\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await query.execute()\n            })\n          }\n\n          it(`should execute a query with ${funcName}(*) over() in select clause`, async () => {\n            const query = ctx.db\n              .selectFrom('person')\n              .select([\n                ctx.db.fn[`${funcName}All`]().over().as(funcName),\n                (eb) =>\n                  eb.fn[`${funcName}All`]().over().as(`another_${funcName}`),\n              ])\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: [\n                  `select ${funcName}(*) over() as \"${funcName}\",`,\n                  `${funcName}(*) over() as \"another_${funcName}\"`,\n                  'from \"person\"',\n                ],\n                parameters: [],\n              },\n              mysql: {\n                sql: [\n                  `select ${funcName}(*) over() as \\`${funcName}\\`,`,\n                  `${funcName}(*) over() as \\`another_${funcName}\\``,\n                  'from `person`',\n                ],\n                parameters: [],\n              },\n              mssql: {\n                sql: [\n                  `select ${funcName}(*) over() as \"${funcName}\",`,\n                  `${funcName}(*) over() as \"another_${funcName}\"`,\n                  'from \"person\"',\n                ],\n                parameters: [],\n              },\n              sqlite: {\n                sql: [\n                  `select ${funcName}(*) over() as \"${funcName}\",`,\n                  `${funcName}(*) over() as \"another_${funcName}\"`,\n                  'from \"person\"',\n                ],\n                parameters: [],\n              },\n            })\n\n            await query.execute()\n          })\n\n          if (dialect === 'postgres' || dialect === 'sqlite') {\n            it(`should execute a query with ${funcName}(*) filter(where ...) in select clause`, async () => {\n              const query = ctx.db\n                .selectFrom('person')\n                .select([\n                  ctx.db.fn[`${funcName}All`]()\n                    .filterWhere('gender', '=', 'female')\n                    .as(funcName),\n                  (eb) =>\n                    eb.fn[`${funcName}All`]()\n                      .filterWhere('gender', '=', 'female')\n                      .as(`another_${funcName}`),\n                ])\n\n              testSql(query, dialect, {\n                postgres: {\n                  sql: [\n                    `select ${funcName}(*)`,\n                    `filter(where \"gender\" = $1) as \"${funcName}\",`,\n                    `${funcName}(*)`,\n                    `filter(where \"gender\" = $2) as \"another_${funcName}\"`,\n                    'from \"person\"',\n                  ],\n                  parameters: ['female', 'female'],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: {\n                  sql: [\n                    `select ${funcName}(*)`,\n                    `filter(where \"gender\" = ?) as \"${funcName}\",`,\n                    `${funcName}(*)`,\n                    `filter(where \"gender\" = ?) as \"another_${funcName}\"`,\n                    'from \"person\"',\n                  ],\n                  parameters: ['female', 'female'],\n                },\n              })\n\n              await query.execute()\n            })\n          }\n        }\n      })\n    }\n\n    it('should execute \"dynamic\" aggregate functions', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .$if(dialect === 'mssql', (qb) => qb.groupBy('person.first_name'))\n        .select([\n          ctx.db.fn\n            .agg('rank')\n            .over((ob) => (dialect === 'mssql' ? ob.orderBy('first_name') : ob))\n            .as('rank'),\n          (eb) =>\n            eb.fn\n              .agg('rank')\n              .over((ob) =>\n                dialect === 'mssql' ? ob.orderBy('first_name') : ob,\n              )\n              .as('another_rank'),\n        ])\n        .$if(dialect === 'postgres' || dialect === 'mssql', (qb) =>\n          qb.select((eb) =>\n            eb.fn\n              .agg('string_agg', ['first_name', sql.lit(',')])\n              .$call((eb) => (dialect === 'mssql' ? eb : eb.distinct()))\n              .as('first_names'),\n          ),\n        )\n        .$if(dialect === 'mysql' || dialect === 'sqlite', (qb) =>\n          qb.select((eb) =>\n            eb.fn\n              .agg('group_concat', ['first_name'])\n              .distinct()\n              .as('first_names'),\n          ),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            'select rank() over() as \"rank\",',\n            'rank() over() as \"another_rank\",',\n            `string_agg(distinct \"first_name\", ',') as \"first_names\"`,\n            'from \"person\"',\n          ],\n          parameters: [],\n        },\n        mysql: {\n          sql: [\n            'select rank() over() as `rank`,',\n            'rank() over() as `another_rank`,',\n            'group_concat(distinct `first_name`) as `first_names`',\n            'from `person`',\n          ],\n          parameters: [],\n        },\n        mssql: {\n          sql: [\n            'select rank() over(order by \"first_name\") as \"rank\",',\n            'rank() over(order by \"first_name\") as \"another_rank\",',\n            `string_agg(\"first_name\", ',') as \"first_names\"`,\n            'from \"person\"',\n            'group by \"person\".\"first_name\"',\n          ],\n          parameters: [],\n        },\n        sqlite: {\n          sql: [\n            'select rank() over() as \"rank\",',\n            'rank() over() as \"another_rank\",',\n            'group_concat(distinct \"first_name\") as \"first_names\"',\n            'from \"person\"',\n          ],\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    describe('should execute order-sensitive aggregate functions', () => {\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'sqlite'\n      ) {\n        const isMySql = dialect === 'mysql'\n        const funcName = isMySql ? 'group_concat' : 'string_agg'\n        const funcArgs: Array<ReferenceExpression<Database, 'person'>> = [\n          'first_name',\n        ]\n        if (!isMySql) {\n          funcArgs.push(sql.lit(','))\n        }\n\n        it(`should execute a query with ${funcName}(column order by column) in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .select((eb) =>\n              eb.fn\n                .agg(funcName, funcArgs)\n                .orderBy('first_name', 'desc')\n                .as('first_names'),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select ${funcName}(\"first_name\", ',' order by \"first_name\" desc) as \"first_names\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n            mysql: {\n              sql: [\n                `select ${funcName}(\\`first_name\\` order by \\`first_name\\` desc) as \\`first_names\\``,\n                `from \\`person\\``,\n              ],\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: [\n                `select ${funcName}(\"first_name\", ',' order by \"first_name\" desc) as \"first_names\"`,\n                `from \"person\"`,\n              ],\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n      }\n\n      if (dialect === 'postgres' || dialect === 'mssql') {\n        it(`should execute a query with within group (order by column) in select clause`, async () => {\n          const query = ctx.db.selectFrom('toy').select((eb) =>\n            eb.fn\n              .agg('percentile_cont', [sql.lit(0.5)])\n              .withinGroupOrderBy('toy.price')\n              .$call((ab) => (dialect === 'mssql' ? ab.over() : ab))\n              .as('median_price'),\n          )\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: [\n                `select percentile_cont(0.5) within group (order by \"toy\".\"price\") as \"median_price\"`,\n                `from \"toy\"`,\n              ],\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: [\n                `select percentile_cont(0.5) within group (order by \"toy\".\"price\") over() as \"median_price\"`,\n                `from \"toy\"`,\n              ],\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await query.execute()\n        })\n      }\n    })\n  })\n}\n\nfunction getAggregateFunctionFromTestContext<TB extends keyof Database>(\n  ctx: TestContext,\n  funcName: (typeof funcNames)[number],\n): AggregateFunction<TB> {\n  return ctx.db.fn[funcName] as any\n}\n\nfunction getAggregateFunctionFromExpressionBuilder<TB extends keyof Database>(\n  eb: ExpressionBuilder<Database, TB>,\n  funcName: (typeof funcNames)[number],\n): AggregateFunction<TB> {\n  return eb.fn[funcName] as any\n}\n\ntype AggregateFunction<\n  TB extends keyof Database,\n  C extends SimpleReferenceExpression<Database, TB> = SimpleReferenceExpression<\n    Database,\n    TB\n  >,\n> = (column: C) => AggregateFunctionBuilder<Database, TB>\n"
  },
  {
    "path": "test/node/src/array.test.ts",
    "content": "import { Generated, Kysely, sql } from '../../..'\n\nimport {\n  destroyTest,\n  initTest,\n  TestContext,\n  expect,\n  Database,\n  insertDefaultDataSet,\n  clearDatabase,\n  Person,\n  DIALECTS,\n} from './test-setup.js'\n\ninterface PersonWithArrays extends Person {\n  id: Generated<number>\n  lucky_numbers: number[]\n  nicknames: string[] | null\n}\n\nif (DIALECTS.includes('postgres')) {\n  const dialect = 'postgres'\n\n  describe(`${dialect} array tests`, () => {\n    let ctx: TestContext\n    let db: Kysely<Omit<Database, 'person'> & { person: PersonWithArrays }>\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n\n      await ctx.db.schema\n        .alterTable('person')\n        .addColumn('lucky_numbers', sql`integer[]`, (col) =>\n          col.notNull().defaultTo(sql`ARRAY[]::integer[]`),\n        )\n        .addColumn('nicknames', sql`text[]`)\n        .execute()\n\n      db = ctx.db as any\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n\n      await db\n        .updateTable('person')\n        .set({\n          nicknames: ['Jenny', 'Jen'],\n          lucky_numbers: [7, 42],\n        })\n        .where('first_name', '=', 'Jennifer')\n        .execute()\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('array columns should get returned as arrays by default', async () => {\n      const jennifer = await db\n        .selectFrom('person')\n        .where('first_name', '=', 'Jennifer')\n        .select(['first_name', 'lucky_numbers', 'nicknames'])\n        .executeTakeFirstOrThrow()\n\n      expect(jennifer).to.eql({\n        first_name: 'Jennifer',\n        lucky_numbers: [7, 42],\n        nicknames: ['Jenny', 'Jen'],\n      })\n    })\n\n    it('should filter using the `any` function', async () => {\n      const jennifer = await db\n        .selectFrom('person')\n        .where((eb) => eb(eb.val(7), '=', eb.fn.any('lucky_numbers')))\n        .select(['first_name', 'lucky_numbers', 'nicknames'])\n        .executeTakeFirstOrThrow()\n\n      expect(jennifer).to.eql({\n        first_name: 'Jennifer',\n        lucky_numbers: [7, 42],\n        nicknames: ['Jenny', 'Jen'],\n      })\n    })\n\n    it('should filter using the `any` function on a nullable column', async () => {\n      const jennifer = await db\n        .selectFrom('person')\n        .where((eb) => eb(eb.val('Jen'), '=', eb.fn.any('nicknames')))\n        .select(['first_name', 'lucky_numbers', 'nicknames'])\n        .executeTakeFirstOrThrow()\n\n      expect(jennifer).to.eql({\n        first_name: 'Jennifer',\n        lucky_numbers: [7, 42],\n        nicknames: ['Jenny', 'Jen'],\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/async-dispose.test.ts",
    "content": "import {\n  CompiledQuery,\n  DatabaseConnection,\n  DummyDriver,\n  Kysely,\n  PostgresAdapter,\n  PostgresIntrospector,\n  PostgresQueryCompiler,\n  QueryId,\n  QueryResult,\n  RootOperationNode,\n  sql,\n} from '../../..'\nimport { expect } from './test-setup'\n\ndescribe('async dispose', function () {\n  it('should call destroy ', async () => {\n    const steps: string[] = []\n\n    {\n      await using db = new Kysely({\n        dialect: {\n          createAdapter: () => new PostgresAdapter(),\n          createDriver: () =>\n            new (class extends DummyDriver {\n              async acquireConnection() {\n                return new (class implements DatabaseConnection {\n                  async executeQuery<R>(): Promise<QueryResult<R>> {\n                    steps.push('executed')\n                    return { rows: [] }\n                  }\n                  streamQuery<R>(): AsyncIterableIterator<QueryResult<R>> {\n                    throw new Error('Method not implemented.')\n                  }\n                })()\n              }\n              async destroy(): Promise<void> {\n                steps.push('destroyed')\n              }\n            })(),\n          createIntrospector: (db) => new PostgresIntrospector(db),\n          createQueryCompiler: () =>\n            new (class extends PostgresQueryCompiler {\n              compileQuery(\n                node: RootOperationNode,\n                queryId: QueryId,\n              ): CompiledQuery<unknown> {\n                const compiled = super.compileQuery(node, queryId)\n                steps.push('compiled')\n                return compiled\n              }\n            })(),\n        },\n      })\n\n      await sql`select 1`.execute(db)\n    }\n\n    steps.push('after runScope')\n\n    expect(steps).to.length.to.be.greaterThan(1)\n    expect(steps).to.deep.equal([\n      'compiled',\n      'executed',\n      'destroyed',\n      'after runScope',\n    ])\n  })\n})\n"
  },
  {
    "path": "test/node/src/camel-case.test.ts",
    "content": "import {\n  CamelCasePlugin,\n  Generated,\n  Kysely,\n  ParseJSONResultsPlugin,\n  RawBuilder,\n  sql,\n} from '../../../'\n\nimport {\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  createTableWithId,\n  DIALECTS,\n  NOT_SUPPORTED,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: camel case test`, () => {\n    let ctx: TestContext\n    let camelDb: Kysely<CamelDatabase>\n\n    interface CamelPerson {\n      id: Generated<number>\n      firstName: string\n      lastName: string\n      preferences: {\n        disable_emails: boolean\n      }\n      addressRow1: string\n    }\n\n    interface CamelDatabase {\n      camelPerson: CamelPerson\n    }\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n\n      camelDb = new Kysely<CamelDatabase>({\n        ...ctx.config,\n        plugins: [new CamelCasePlugin()],\n      })\n\n      await camelDb.schema.dropTable('camelPerson').ifExists().execute()\n      await createTableWithId(camelDb.schema, dialect, 'camelPerson')\n        .addColumn('firstName', 'varchar(255)')\n        .addColumn('lastName', 'varchar(255)')\n        .addColumn(\n          'preferences',\n          dialect === 'mssql' ? 'varchar(8000)' : 'json',\n        )\n        .addColumn('addressRow1', 'varchar(255)')\n        .execute()\n    })\n\n    beforeEach(async () => {\n      await camelDb\n        .insertInto('camelPerson')\n        .values([\n          {\n            firstName: 'Jennifer',\n            lastName: 'Aniston',\n            preferences: json({ disable_emails: true }),\n            addressRow1: '123 Main St',\n          },\n          {\n            firstName: 'Arnold',\n            lastName: 'Schwarzenegger',\n            preferences: json({ disable_emails: true }),\n            addressRow1: '123 Main St',\n          },\n        ])\n        .execute()\n    })\n\n    afterEach(async () => {\n      await camelDb.deleteFrom('camelPerson').execute()\n    })\n\n    after(async () => {\n      await camelDb.schema.dropTable('camelPerson').ifExists().execute()\n      await camelDb.destroy()\n      await destroyTest(ctx)\n    })\n\n    // Can't run this test on SQLite because we can't access the same database\n    // from the other Kysely instance.\n    if (dialect !== 'sqlite') {\n      it('should have created the table and its columns in snake_case', async () => {\n        const result = await sql<any>`select * from camel_person`.execute(\n          ctx.db,\n        )\n\n        expect(result.rows).to.have.length(2)\n        expect(result.rows[0].id).to.be.a('number')\n        expect(result.rows[0].first_name).to.be.a('string')\n        expect(result.rows[0].last_name).to.be.a('string')\n      })\n    }\n\n    it('should convert a select query between camelCase and snake_case', async () => {\n      const query = camelDb\n        .selectFrom('camelPerson')\n        .select('camelPerson.firstName')\n        .innerJoin(\n          'camelPerson as camelPerson2',\n          'camelPerson2.id',\n          'camelPerson.id',\n        )\n        .orderBy('camelPerson.firstName')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            `select \"camel_person\".\"first_name\"`,\n            `from \"camel_person\"`,\n            `inner join \"camel_person\" as \"camel_person2\" on \"camel_person2\".\"id\" = \"camel_person\".\"id\"`,\n            `order by \"camel_person\".\"first_name\"`,\n          ],\n          parameters: [],\n        },\n        mysql: {\n          sql: [\n            'select `camel_person`.`first_name`',\n            'from `camel_person`',\n            'inner join `camel_person` as `camel_person2` on `camel_person2`.`id` = `camel_person`.`id`',\n            'order by `camel_person`.`first_name`',\n          ],\n          parameters: [],\n        },\n        mssql: {\n          sql: [\n            `select \"camel_person\".\"first_name\"`,\n            `from \"camel_person\"`,\n            `inner join \"camel_person\" as \"camel_person2\" on \"camel_person2\".\"id\" = \"camel_person\".\"id\"`,\n            `order by \"camel_person\".\"first_name\"`,\n          ],\n          parameters: [],\n        },\n        sqlite: {\n          sql: [\n            `select \"camel_person\".\"first_name\"`,\n            `from \"camel_person\"`,\n            `inner join \"camel_person\" as \"camel_person2\" on \"camel_person2\".\"id\" = \"camel_person\".\"id\"`,\n            `order by \"camel_person\".\"first_name\"`,\n          ],\n          parameters: [],\n        },\n      })\n\n      const result = await query.execute()\n      expect(result).to.have.length(2)\n      expect(result).to.containSubset([\n        { firstName: 'Jennifer' },\n        { firstName: 'Arnold' },\n      ])\n    })\n\n    it('should convert a select query between camelCase and snake_case in a transaction', async () => {\n      await camelDb.transaction().execute(async (trx) => {\n        const query = trx\n          .selectFrom('camelPerson')\n          .select('camelPerson.firstName')\n          .innerJoin(\n            'camelPerson as camelPerson2',\n            'camelPerson2.id',\n            'camelPerson.id',\n          )\n          .orderBy('camelPerson.firstName')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              `select \"camel_person\".\"first_name\"`,\n              `from \"camel_person\"`,\n              `inner join \"camel_person\" as \"camel_person2\" on \"camel_person2\".\"id\" = \"camel_person\".\"id\"`,\n              `order by \"camel_person\".\"first_name\"`,\n            ],\n            parameters: [],\n          },\n          mysql: {\n            sql: [\n              'select `camel_person`.`first_name`',\n              'from `camel_person`',\n              'inner join `camel_person` as `camel_person2` on `camel_person2`.`id` = `camel_person`.`id`',\n              'order by `camel_person`.`first_name`',\n            ],\n            parameters: [],\n          },\n          mssql: {\n            sql: [\n              `select \"camel_person\".\"first_name\"`,\n              `from \"camel_person\"`,\n              `inner join \"camel_person\" as \"camel_person2\" on \"camel_person2\".\"id\" = \"camel_person\".\"id\"`,\n              `order by \"camel_person\".\"first_name\"`,\n            ],\n            parameters: [],\n          },\n          sqlite: {\n            sql: [\n              `select \"camel_person\".\"first_name\"`,\n              `from \"camel_person\"`,\n              `inner join \"camel_person\" as \"camel_person2\" on \"camel_person2\".\"id\" = \"camel_person\".\"id\"`,\n              `order by \"camel_person\".\"first_name\"`,\n            ],\n            parameters: [],\n          },\n        })\n\n        const result = await query.execute()\n        expect(result).to.have.length(2)\n        expect(result).to.containSubset([\n          { firstName: 'Jennifer' },\n          { firstName: 'Arnold' },\n        ])\n      })\n    })\n\n    it('should convert alter table query between camelCase and snake_case', async () => {\n      const query = camelDb.schema\n        .alterTable('camelPerson')\n        .addColumn('middleName', 'text', (col) =>\n          col.references('camelPerson.firstName'),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'alter table \"camel_person\" add column \"middle_name\" text references \"camel_person\" (\"first_name\")',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'alter table `camel_person` add column `middle_name` text references `camel_person` (`first_name`)',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'alter table \"camel_person\" add \"middle_name\" text references \"camel_person\" (\"first_name\")',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'alter table \"camel_person\" add column \"middle_name\" text references \"camel_person\" (\"first_name\")',\n          parameters: [],\n        },\n      })\n    })\n\n    it('should convert delete from table using query between camelCase and snake_case', async () => {\n      const query = camelDb\n        .deleteFrom('camelPerson as c')\n        .using('camelPerson')\n        .where('camelPerson.firstName', '=', 'Arnold')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `delete from \"camel_person\" as \"c\" using \"camel_person\" where \"camel_person\".\"first_name\" = $1`,\n          parameters: ['Arnold'],\n        },\n        mysql: {\n          sql: 'delete from `camel_person` as `c` using `camel_person` where `camel_person`.`first_name` = ?',\n          parameters: ['Arnold'],\n        },\n        mssql: {\n          sql: `delete from \"camel_person\" as \"c\" using \"camel_person\" where \"camel_person\".\"first_name\" = @1`,\n          parameters: ['Arnold'],\n        },\n        sqlite: {\n          sql: `delete from \"camel_person\" as \"c\" using \"camel_person\" where \"camel_person\".\"first_name\" = ?`,\n          parameters: ['Arnold'],\n        },\n      })\n    })\n\n    it('should map nested objects by default', async () => {\n      let db = camelDb.withoutPlugins()\n\n      if (dialect === 'mssql' || dialect === 'sqlite') {\n        db = db.withPlugin(new ParseJSONResultsPlugin())\n      }\n\n      db = db.withPlugin(new CamelCasePlugin())\n\n      const data = await db\n        .selectFrom('camelPerson')\n        .selectAll()\n        .executeTakeFirstOrThrow()\n\n      expect(data.preferences).to.eql({\n        disableEmails: true,\n      })\n    })\n\n    it('should respect maintainNestedObjectKeys', async () => {\n      let db = camelDb.withoutPlugins()\n\n      if (dialect === 'mssql' || dialect === 'sqlite') {\n        db = db.withPlugin(new ParseJSONResultsPlugin())\n      }\n\n      db = db.withPlugin(\n        new CamelCasePlugin({ maintainNestedObjectKeys: true }),\n      )\n\n      const data = await db\n        .selectFrom('camelPerson')\n        .selectAll()\n        .executeTakeFirstOrThrow()\n\n      expect(data.preferences).to.eql({\n        disable_emails: true,\n      })\n    })\n\n    it('should respect `underscoreBeforeDigits` and not add a second underscore in a nested query', async () => {\n      const db = camelDb\n        .withoutPlugins()\n        .withPlugin(new CamelCasePlugin({ underscoreBeforeDigits: true }))\n\n      const query = db\n        .selectFrom(\n          db\n            .selectFrom('camelPerson')\n            .select('addressRow1')\n            .as('originalQuery'),\n        )\n        .selectAll()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            `select * from (select \"address_row_1\" from \"camel_person\") as \"original_query\"`,\n          ],\n          parameters: [],\n        },\n        mysql: {\n          sql: [\n            'select * from (select `address_row_1` from `camel_person`) as `original_query`',\n          ],\n          parameters: [],\n        },\n        mssql: {\n          sql: [\n            `select * from (select \"address_row_1\" from \"camel_person\") as \"original_query\"`,\n          ],\n          parameters: [],\n        },\n        sqlite: {\n          sql: [\n            `select * from (select \"address_row_1\" from \"camel_person\") as \"original_query\"`,\n          ],\n          parameters: [],\n        },\n      })\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      it('should convert merge queries', async () => {\n        const query = camelDb\n          .mergeInto('camelPerson')\n          .using(\n            'camelPerson as anotherCamelPerson',\n            'camelPerson.firstName',\n            'anotherCamelPerson.firstName',\n          )\n          .whenMatched()\n          .thenUpdateSet((eb) => ({\n            firstName: sql<string>`concat(${eb.ref('anotherCamelPerson.firstName')}, ${sql.lit('2')})`,\n          }))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              `merge into \"camel_person\"`,\n              `using \"camel_person\" as \"another_camel_person\" on \"camel_person\".\"first_name\" = \"another_camel_person\".\"first_name\"`,\n              `when matched then update set \"first_name\" = concat(\"another_camel_person\".\"first_name\", '2')`,\n            ],\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: [\n              `merge into \"camel_person\"`,\n              `using \"camel_person\" as \"another_camel_person\" on \"camel_person\".\"first_name\" = \"another_camel_person\".\"first_name\"`,\n              `when matched then update set \"first_name\" = concat(\"another_camel_person\".\"first_name\", '2');`,\n            ],\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n      })\n    }\n  })\n}\n\nfunction json<T>(obj: T): RawBuilder<T> {\n  return sql`${JSON.stringify(obj)}`\n}\n"
  },
  {
    "path": "test/node/src/case.test.ts",
    "content": "import { sql } from '../../..'\nimport {\n  DIALECTS,\n  TestContext,\n  clearDatabase,\n  destroyTest,\n  initTest,\n  insertDefaultDataSet,\n  testSql,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: case`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should execute a query with a case...when...then...end operator', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select((eb) =>\n          eb.case().when('gender', '=', 'male').then('Mr.').end().as('title'),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select case when \"gender\" = $1 then $2 end as \"title\" from \"person\"`,\n          parameters: ['male', 'Mr.'],\n        },\n        mysql: {\n          sql: 'select case when `gender` = ? then ? end as `title` from `person`',\n          parameters: ['male', 'Mr.'],\n        },\n        mssql: {\n          sql: `select case when \"gender\" = @1 then @2 end as \"title\" from \"person\"`,\n          parameters: ['male', 'Mr.'],\n        },\n        sqlite: {\n          sql: `select case when \"gender\" = ? then ? end as \"title\" from \"person\"`,\n          parameters: ['male', 'Mr.'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should execute a query with a case...value...when...then...end operator', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select((eb) =>\n          eb.case('gender').when('male').then('Mr.').end().as('title'),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select case \"gender\" when $1 then $2 end as \"title\" from \"person\"`,\n          parameters: ['male', 'Mr.'],\n        },\n        mysql: {\n          sql: 'select case `gender` when ? then ? end as `title` from `person`',\n          parameters: ['male', 'Mr.'],\n        },\n        mssql: {\n          sql: `select case \"gender\" when @1 then @2 end as \"title\" from \"person\"`,\n          parameters: ['male', 'Mr.'],\n        },\n        sqlite: {\n          sql: `select case \"gender\" when ? then ? end as \"title\" from \"person\"`,\n          parameters: ['male', 'Mr.'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should execute a query with a case...when...then...when...then...end operator', async () => {\n      const query = ctx.db.selectFrom('person').select((eb) =>\n        eb\n          .case()\n          .when(eb('gender', '=', 'male'))\n          .then(sql.lit('Mr.'))\n          .when(eb('gender', '=', 'female'))\n          .then(sql.lit('Mrs.'))\n          .end()\n          .as('title'),\n      )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            `select case when \"gender\" = $1 then 'Mr.'`,\n            `when \"gender\" = $2 then 'Mrs.'`,\n            `end as \"title\" from \"person\"`,\n          ],\n          parameters: ['male', 'female'],\n        },\n        mysql: {\n          sql: [\n            \"select case when `gender` = ? then 'Mr.'\",\n            \"when `gender` = ? then 'Mrs.'\",\n            'end as `title` from `person`',\n          ],\n          parameters: ['male', 'female'],\n        },\n        mssql: {\n          sql: [\n            `select case when \"gender\" = @1 then 'Mr.'`,\n            `when \"gender\" = @2 then 'Mrs.'`,\n            `end as \"title\" from \"person\"`,\n          ],\n          parameters: ['male', 'female'],\n        },\n        sqlite: {\n          sql: [\n            `select case when \"gender\" = ? then 'Mr.'`,\n            `when \"gender\" = ? then 'Mrs.'`,\n            `end as \"title\" from \"person\"`,\n          ],\n          parameters: ['male', 'female'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should execute a query with a case...value...when...then...when...then...end operator', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select((eb) =>\n          eb\n            .case('gender')\n            .when(sql.lit('male'))\n            .then(sql.lit('Mr.'))\n            .when(sql.lit('female'))\n            .then(sql.lit('Mrs.'))\n            .end()\n            .as('title'),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            `select case \"gender\" when 'male' then 'Mr.'`,\n            `when 'female' then 'Mrs.'`,\n            `end as \"title\" from \"person\"`,\n          ],\n          parameters: [],\n        },\n        mysql: {\n          sql: [\n            \"select case `gender` when 'male' then 'Mr.'\",\n            \"when 'female' then 'Mrs.'\",\n            'end as `title` from `person`',\n          ],\n          parameters: [],\n        },\n        mssql: {\n          sql: [\n            `select case \"gender\" when 'male' then 'Mr.'`,\n            `when 'female' then 'Mrs.'`,\n            `end as \"title\" from \"person\"`,\n          ],\n          parameters: [],\n        },\n        sqlite: {\n          sql: [\n            `select case \"gender\" when 'male' then 'Mr.'`,\n            `when 'female' then 'Mrs.'`,\n            `end as \"title\" from \"person\"`,\n          ],\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should execute a query with a case...when...then...when...then...else...end operator', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select((eb) =>\n          eb\n            .case()\n            .when('gender', '=', 'male')\n            .then('Mr.')\n            .when('gender', '=', 'female')\n            .then('Mrs.')\n            .else(null)\n            .end()\n            .as('title'),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            `select case when \"gender\" = $1 then $2`,\n            `when \"gender\" = $3 then $4`,\n            `else null end as \"title\" from \"person\"`,\n          ],\n          parameters: ['male', 'Mr.', 'female', 'Mrs.'],\n        },\n        mysql: {\n          sql: [\n            'select case when `gender` = ? then ?',\n            'when `gender` = ? then ?',\n            'else null end as `title` from `person`',\n          ],\n          parameters: ['male', 'Mr.', 'female', 'Mrs.'],\n        },\n        mssql: {\n          sql: [\n            `select case when \"gender\" = @1 then @2`,\n            `when \"gender\" = @3 then @4`,\n            `else null end as \"title\" from \"person\"`,\n          ],\n          parameters: ['male', 'Mr.', 'female', 'Mrs.'],\n        },\n        sqlite: {\n          sql: [\n            `select case when \"gender\" = ? then ?`,\n            `when \"gender\" = ? then ?`,\n            `else null end as \"title\" from \"person\"`,\n          ],\n          parameters: ['male', 'Mr.', 'female', 'Mrs.'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should execute a query with a case...value...when...then...when...then...(case...when...then...else...end)...end operator', async () => {\n      const query = ctx.db.selectFrom('person').select((eb) =>\n        eb\n          .case('gender')\n          .when('male')\n          .then('Mr.')\n          .when('female')\n          .then(\n            eb\n              .case()\n              .when(\n                eb.or([\n                  eb('marital_status', '=', 'single'),\n                  eb('marital_status', 'is', null),\n                ]),\n              )\n              .then('Ms.')\n              .else('Mrs.')\n              .end(),\n          )\n          .end()\n          .as('title'),\n      )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            'select case \"gender\" when $1 then $2',\n            'when $3 then',\n            'case when (\"marital_status\" = $4 or',\n            '\"marital_status\" is null) then $5',\n            'else $6 end',\n            'end as \"title\" from \"person\"',\n          ],\n          parameters: ['male', 'Mr.', 'female', 'single', 'Ms.', 'Mrs.'],\n        },\n        mysql: {\n          sql: [\n            'select case `gender` when ? then ?',\n            'when ? then',\n            'case when (`marital_status` = ? or',\n            '`marital_status` is null) then ?',\n            'else ? end',\n            'end as `title` from `person`',\n          ],\n          parameters: ['male', 'Mr.', 'female', 'single', 'Ms.', 'Mrs.'],\n        },\n        mssql: {\n          sql: [\n            'select case \"gender\" when @1 then @2',\n            'when @3 then',\n            'case when (\"marital_status\" = @4 or',\n            '\"marital_status\" is null) then @5',\n            'else @6 end',\n            'end as \"title\" from \"person\"',\n          ],\n          parameters: ['male', 'Mr.', 'female', 'single', 'Ms.', 'Mrs.'],\n        },\n        sqlite: {\n          sql: [\n            'select case \"gender\" when ? then ?',\n            'when ? then',\n            'case when (\"marital_status\" = ? or',\n            '\"marital_status\" is null) then ?',\n            'else ? end',\n            'end as \"title\" from \"person\"',\n          ],\n          parameters: ['male', 'Mr.', 'female', 'single', 'Ms.', 'Mrs.'],\n        },\n      })\n\n      await query.execute()\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/clear.test.ts",
    "content": "import {\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  NOT_SUPPORTED,\n  DIALECTS,\n  limit,\n} from './test-setup'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect} clear`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should clear select', () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['id', 'first_name', 'last_name'])\n        .clearSelect()\n        .select(['id'])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select \"id\" from \"person\"`,\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `id` from `person`',\n          parameters: [],\n        },\n        mssql: {\n          sql: `select \"id\" from \"person\"`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: `select \"id\" from \"person\"`,\n          parameters: [],\n        },\n      })\n    })\n\n    it('SelectQueryBuilder should clear where', () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .where('gender', '=', 'other')\n        .clearWhere()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select * from \"person\"`,\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select * from `person`',\n          parameters: [],\n        },\n        mssql: {\n          sql: `select * from \"person\"`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: `select * from \"person\"`,\n          parameters: [],\n        },\n      })\n    })\n\n    it('OnConflictBuilder should clear where', () => {\n      const query = ctx.db\n        .insertInto('person')\n        .onConflict((b) => b.where('id', '=', 3).clearWhere().doNothing())\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `insert into \"person\" on conflict do nothing`,\n          parameters: [],\n        },\n        mysql: {\n          sql: 'insert into `person` on conflict do nothing',\n          parameters: [],\n        },\n        mssql: {\n          sql: `insert into \"person\" on conflict do nothing`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: `insert into \"person\" on conflict do nothing`,\n          parameters: [],\n        },\n      })\n    })\n\n    it('OnConflictUpdateBuilder should clear where', () => {\n      const query = ctx.db\n        .insertInto('person')\n        .onConflict((b) =>\n          b\n            .doUpdateSet({ gender: 'other' })\n            .where('gender', '=', 'male')\n            .clearWhere(),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `insert into \"person\" on conflict do update set \"gender\" = $1`,\n          parameters: ['other'],\n        },\n        mysql: {\n          sql: 'insert into `person` on conflict do update set `gender` = ?',\n          parameters: ['other'],\n        },\n        mssql: {\n          sql: `insert into \"person\" on conflict do update set \"gender\" = @1`,\n          parameters: ['other'],\n        },\n        sqlite: {\n          sql: `insert into \"person\" on conflict do update set \"gender\" = ?`,\n          parameters: ['other'],\n        },\n      })\n    })\n\n    it('UpdateQueryBuilder should clear where', () => {\n      const query = ctx.db\n        .updateTable('person')\n        .set({ gender: 'other' })\n        .where('gender', '=', 'other')\n        .clearWhere()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `update \"person\" set \"gender\" = $1`,\n          parameters: ['other'],\n        },\n        mysql: {\n          sql: 'update `person` set `gender` = ?',\n          parameters: ['other'],\n        },\n        mssql: {\n          sql: `update \"person\" set \"gender\" = @1`,\n          parameters: ['other'],\n        },\n        sqlite: {\n          sql: `update \"person\" set \"gender\" = ?`,\n          parameters: ['other'],\n        },\n      })\n    })\n\n    it('DeleteQueryBuilder should clear where', () => {\n      const query = ctx.db\n        .deleteFrom('person')\n        .where('gender', '=', 'other')\n        .clearWhere()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `delete from \"person\"`,\n          parameters: [],\n        },\n        mysql: {\n          sql: 'delete from `person`',\n          parameters: [],\n        },\n        mssql: {\n          sql: `delete from \"person\"`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: `delete from \"person\"`,\n          parameters: [],\n        },\n      })\n    })\n\n    it('InsertQueryBuilder should clear returning', () => {\n      const query = ctx.db\n        .insertInto('person')\n        .values({ first_name: 'Bruce', last_name: 'Willis', gender: 'male' })\n        .returning(['first_name'])\n        .clearReturning()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)`,\n          parameters: ['Bruce', 'Willis', 'male'],\n        },\n        mysql: {\n          sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n          parameters: ['Bruce', 'Willis', 'male'],\n        },\n        mssql: {\n          sql: `insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3)`,\n          parameters: ['Bruce', 'Willis', 'male'],\n        },\n        sqlite: {\n          sql: `insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)`,\n          parameters: ['Bruce', 'Willis', 'male'],\n        },\n      })\n    })\n\n    it('UpdateQueryBuilder should clear returning', () => {\n      const query = ctx.db\n        .updateTable('person')\n        .set({ marital_status: 'married' })\n        .where('first_name', '=', 'Bruce')\n        .returning(['first_name'])\n        .clearReturning()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `update \"person\" set \"marital_status\" = $1 where \"first_name\" = $2`,\n          parameters: ['married', 'Bruce'],\n        },\n        mysql: {\n          sql: 'update `person` set `marital_status` = ? where `first_name` = ?',\n          parameters: ['married', 'Bruce'],\n        },\n        mssql: {\n          sql: `update \"person\" set \"marital_status\" = @1 where \"first_name\" = @2`,\n          parameters: ['married', 'Bruce'],\n        },\n        sqlite: {\n          sql: `update \"person\" set \"marital_status\" = ? where \"first_name\" = ?`,\n          parameters: ['married', 'Bruce'],\n        },\n      })\n    })\n\n    it('DeleteQueryBuilder should clear returning', () => {\n      const query = ctx.db\n        .deleteFrom('person')\n        .where('first_name', '=', 'James')\n        .returning(['first_name'])\n        .clearReturning()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `delete from \"person\" where \"first_name\" = $1`,\n          parameters: ['James'],\n        },\n        mysql: {\n          sql: 'delete from `person` where `first_name` = ?',\n          parameters: ['James'],\n        },\n        mssql: {\n          sql: `delete from \"person\" where \"first_name\" = @1`,\n          parameters: ['James'],\n        },\n        sqlite: {\n          sql: `delete from \"person\" where \"first_name\" = ?`,\n          parameters: ['James'],\n        },\n      })\n    })\n\n    it('should clear orderBy', () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .orderBy('id')\n        .clearOrderBy()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select * from \"person\"`,\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select * from `person`',\n          parameters: [],\n        },\n        mssql: {\n          sql: `select * from \"person\"`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: `select * from \"person\"`,\n          parameters: [],\n        },\n      })\n    })\n\n    it('DeleteQueryBuilder clear orderBy', () => {\n      const query = ctx.db\n        .deleteFrom('person')\n        .where('gender', '=', 'male')\n        .orderBy('id')\n        .clearOrderBy()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `delete from \"person\" where \"gender\" = $1`,\n          parameters: ['male'],\n        },\n        mysql: {\n          sql: 'delete from `person` where `gender` = ?',\n          parameters: ['male'],\n        },\n        mssql: {\n          sql: `delete from \"person\" where \"gender\" = @1`,\n          parameters: ['male'],\n        },\n        sqlite: {\n          sql: `delete from \"person\" where \"gender\" = ?`,\n          parameters: ['male'],\n        },\n      })\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') {\n      it('should clear limit', () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .limit(100)\n          .clearLimit()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select * from \"person\"`,\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select * from `person`',\n            parameters: [],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: `select * from \"person\"`,\n            parameters: [],\n          },\n        })\n      })\n\n      it('DeleteQueryBuilder should clear limit', () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .where('gender', '=', 'male')\n          .limit(1)\n          .clearLimit()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `delete from \"person\" where \"gender\" = $1`,\n            parameters: ['male'],\n          },\n          mysql: {\n            sql: 'delete from `person` where `gender` = ?',\n            parameters: ['male'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: `delete from \"person\" where \"gender\" = ?`,\n            parameters: ['male'],\n          },\n        })\n      })\n    }\n\n    it('should clear offset', () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .$call(limit(1, dialect))\n        .offset(100)\n        .clearOffset()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select * from \"person\" limit $1`,\n          parameters: [1],\n        },\n        mysql: {\n          sql: 'select * from `person` limit ?',\n          parameters: [1],\n        },\n        mssql: {\n          sql: `select top(1) * from \"person\"`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: `select * from \"person\" limit ?`,\n          parameters: [1],\n        },\n      })\n    })\n\n    it('should clear groupBy', () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .groupBy('id')\n        .clearGroupBy()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select * from \"person\"`,\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select * from `person`',\n          parameters: [],\n        },\n        mssql: {\n          sql: `select * from \"person\"`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: `select * from \"person\"`,\n          parameters: [],\n        },\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/coalesce.test.ts",
    "content": "import { sql } from '../../..'\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  insertDefaultDataSet,\n  NOT_SUPPORTED,\n  TestContext,\n  testSql,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: coalesce`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql') {\n      it('should coalesce a single item', async () => {\n        const { coalesce } = ctx.db.fn\n\n        const query = ctx.db\n          .selectFrom('person')\n          .select([\n            coalesce('first_name').as('ColumnReference'),\n            coalesce(ctx.db.dynamic.ref('first_name')).as('DynamicReference'),\n            coalesce(sql`${1}`).as('RawBuilder'),\n            coalesce(ctx.db.fn.max('first_name')).as('AggregateFunction'),\n          ])\n          .groupBy(['first_name'])\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'select',\n              'coalesce(\"first_name\") as \"ColumnReference\",',\n              'coalesce(\"first_name\") as \"DynamicReference\",',\n              'coalesce($1) as \"RawBuilder\",',\n              'coalesce(max(\"first_name\")) as \"AggregateFunction\"',\n              'from \"person\"',\n              'group by \"first_name\"',\n            ],\n            parameters: [1],\n          },\n          mysql: {\n            sql: [\n              'select',\n              'coalesce(`first_name`) as `ColumnReference`,',\n              'coalesce(`first_name`) as `DynamicReference`,',\n              'coalesce(?) as `RawBuilder`,',\n              'coalesce(max(`first_name`)) as `AggregateFunction`',\n              'from `person`',\n              'group by `first_name`',\n            ],\n            parameters: [1],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    it('should coalesce two items', async () => {\n      const { coalesce, max } = ctx.db.fn\n\n      const query = ctx.db\n        .selectFrom('person')\n        .select([\n          coalesce('first_name', 'last_name').as('ColumnReference0'),\n          coalesce('first_name', ctx.db.dynamic.ref('last_name')).as(\n            'ColumnReference1',\n          ),\n          ...(dialect === 'postgres' ||\n          dialect === 'mysql' ||\n          dialect === 'sqlite'\n            ? [coalesce('first_name', sql`${1}`).as('ColumnReference2')]\n            : []),\n          coalesce('first_name', max('last_name')).as('ColumnReference3'),\n          coalesce(\n            ctx.db.dynamic.ref('first_name'),\n            ctx.db.dynamic.ref('last_name'),\n          ).as('DynamicReference0'),\n          coalesce(ctx.db.dynamic.ref('first_name'), 'last_name').as(\n            'DynamicReference1',\n          ),\n          ...(dialect === 'postgres' ||\n          dialect === 'mysql' ||\n          dialect === 'sqlite'\n            ? [\n                coalesce(ctx.db.dynamic.ref('first_name'), sql`${2}`).as(\n                  'DynamicReference2',\n                ),\n              ]\n            : []),\n          coalesce(ctx.db.dynamic.ref('first_name'), max('last_name')).as(\n            'DynamicReference3',\n          ),\n          coalesce(sql`${3}`, sql`${4}`).as('RawBuilder0'),\n          coalesce(sql`${5}`, 'last_name').as('RawBuilder1'),\n          coalesce(sql`${6}`, ctx.db.dynamic.ref('last_name')).as(\n            'RawBuilder2',\n          ),\n          coalesce(sql`${7}`, max('last_name')).as('RawBuilder3'),\n          coalesce(max('first_name'), max('last_name')).as(\n            'AggregateFunction0',\n          ),\n          coalesce(max('first_name'), 'last_name').as('AggregateFunction1'),\n          coalesce(max('first_name'), ctx.db.dynamic.ref('last_name')).as(\n            'AggregateFunction2',\n          ),\n          ...(dialect === 'postgres' ||\n          dialect === 'mysql' ||\n          dialect === 'sqlite'\n            ? [coalesce(max('first_name'), sql`${8}`).as('AggregateFunction3')]\n            : []),\n        ])\n        .groupBy(['first_name', 'last_name'])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            'select',\n            'coalesce(\"first_name\", \"last_name\") as \"ColumnReference0\",',\n            'coalesce(\"first_name\", \"last_name\") as \"ColumnReference1\",',\n            'coalesce(\"first_name\", $1) as \"ColumnReference2\",',\n            'coalesce(\"first_name\", max(\"last_name\")) as \"ColumnReference3\",',\n            'coalesce(\"first_name\", \"last_name\") as \"DynamicReference0\",',\n            'coalesce(\"first_name\", \"last_name\") as \"DynamicReference1\",',\n            'coalesce(\"first_name\", $2) as \"DynamicReference2\",',\n            'coalesce(\"first_name\", max(\"last_name\")) as \"DynamicReference3\",',\n            'coalesce($3, $4) as \"RawBuilder0\",',\n            'coalesce($5, \"last_name\") as \"RawBuilder1\",',\n            'coalesce($6, \"last_name\") as \"RawBuilder2\",',\n            'coalesce($7, max(\"last_name\")) as \"RawBuilder3\",',\n            'coalesce(max(\"first_name\"), max(\"last_name\")) as \"AggregateFunction0\",',\n            'coalesce(max(\"first_name\"), \"last_name\") as \"AggregateFunction1\",',\n            'coalesce(max(\"first_name\"), \"last_name\") as \"AggregateFunction2\",',\n            'coalesce(max(\"first_name\"), $8) as \"AggregateFunction3\"',\n            'from \"person\"',\n            'group by \"first_name\", \"last_name\"',\n          ],\n          parameters: [1, 2, 3, 4, 5, 6, 7, 8],\n        },\n        mysql: {\n          sql: [\n            'select',\n            'coalesce(`first_name`, `last_name`) as `ColumnReference0`,',\n            'coalesce(`first_name`, `last_name`) as `ColumnReference1`,',\n            'coalesce(`first_name`, ?) as `ColumnReference2`,',\n            'coalesce(`first_name`, max(`last_name`)) as `ColumnReference3`,',\n            'coalesce(`first_name`, `last_name`) as `DynamicReference0`,',\n            'coalesce(`first_name`, `last_name`) as `DynamicReference1`,',\n            'coalesce(`first_name`, ?) as `DynamicReference2`,',\n            'coalesce(`first_name`, max(`last_name`)) as `DynamicReference3`,',\n            'coalesce(?, ?) as `RawBuilder0`,',\n            'coalesce(?, `last_name`) as `RawBuilder1`,',\n            'coalesce(?, `last_name`) as `RawBuilder2`,',\n            'coalesce(?, max(`last_name`)) as `RawBuilder3`,',\n            'coalesce(max(`first_name`), max(`last_name`)) as `AggregateFunction0`,',\n            'coalesce(max(`first_name`), `last_name`) as `AggregateFunction1`,',\n            'coalesce(max(`first_name`), `last_name`) as `AggregateFunction2`,',\n            'coalesce(max(`first_name`), ?) as `AggregateFunction3`',\n            'from `person`',\n            'group by `first_name`, `last_name`',\n          ],\n          parameters: [1, 2, 3, 4, 5, 6, 7, 8],\n        },\n        mssql: {\n          sql: [\n            'select',\n            'coalesce(\"first_name\", \"last_name\") as \"ColumnReference0\",',\n            'coalesce(\"first_name\", \"last_name\") as \"ColumnReference1\",',\n            'coalesce(\"first_name\", max(\"last_name\")) as \"ColumnReference3\",',\n            'coalesce(\"first_name\", \"last_name\") as \"DynamicReference0\",',\n            'coalesce(\"first_name\", \"last_name\") as \"DynamicReference1\",',\n            'coalesce(\"first_name\", max(\"last_name\")) as \"DynamicReference3\",',\n            'coalesce(@1, @2) as \"RawBuilder0\",',\n            'coalesce(@3, \"last_name\") as \"RawBuilder1\",',\n            'coalesce(@4, \"last_name\") as \"RawBuilder2\",',\n            'coalesce(@5, max(\"last_name\")) as \"RawBuilder3\",',\n            'coalesce(max(\"first_name\"), max(\"last_name\")) as \"AggregateFunction0\",',\n            'coalesce(max(\"first_name\"), \"last_name\") as \"AggregateFunction1\",',\n            'coalesce(max(\"first_name\"), \"last_name\") as \"AggregateFunction2\"',\n            'from \"person\"',\n            'group by \"first_name\", \"last_name\"',\n          ],\n          parameters: [3, 4, 5, 6, 7],\n        },\n        sqlite: {\n          sql: [\n            'select',\n            'coalesce(\"first_name\", \"last_name\") as \"ColumnReference0\",',\n            'coalesce(\"first_name\", \"last_name\") as \"ColumnReference1\",',\n            'coalesce(\"first_name\", ?) as \"ColumnReference2\",',\n            'coalesce(\"first_name\", max(\"last_name\")) as \"ColumnReference3\",',\n            'coalesce(\"first_name\", \"last_name\") as \"DynamicReference0\",',\n            'coalesce(\"first_name\", \"last_name\") as \"DynamicReference1\",',\n            'coalesce(\"first_name\", ?) as \"DynamicReference2\",',\n            'coalesce(\"first_name\", max(\"last_name\")) as \"DynamicReference3\",',\n            'coalesce(?, ?) as \"RawBuilder0\",',\n            'coalesce(?, \"last_name\") as \"RawBuilder1\",',\n            'coalesce(?, \"last_name\") as \"RawBuilder2\",',\n            'coalesce(?, max(\"last_name\")) as \"RawBuilder3\",',\n            'coalesce(max(\"first_name\"), max(\"last_name\")) as \"AggregateFunction0\",',\n            'coalesce(max(\"first_name\"), \"last_name\") as \"AggregateFunction1\",',\n            'coalesce(max(\"first_name\"), \"last_name\") as \"AggregateFunction2\",',\n            'coalesce(max(\"first_name\"), ?) as \"AggregateFunction3\"',\n            'from \"person\"',\n            'group by \"first_name\", \"last_name\"',\n          ],\n          parameters: [1, 2, 3, 4, 5, 6, 7, 8],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should coalesce four items', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select([\n          ctx.db.fn\n            .coalesce(\n              'first_name',\n              ctx.db.dynamic.ref('last_name'),\n              ctx.db.fn.max('last_name'),\n              sql.lit('(N/A)'),\n            )\n            .as('name'),\n        ])\n        .groupBy(['first_name', 'last_name'])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            'select',\n            `coalesce(\"first_name\", \"last_name\", max(\"last_name\"), '(N/A)') as \"name\"`,\n            'from \"person\"',\n            'group by \"first_name\", \"last_name\"',\n          ],\n          parameters: [],\n        },\n        mysql: {\n          sql: [\n            'select',\n            \"coalesce(`first_name`, `last_name`, max(`last_name`), '(N/A)') as `name`\",\n            'from `person`',\n            'group by `first_name`, `last_name`',\n          ],\n          parameters: [],\n        },\n        mssql: {\n          sql: [\n            'select',\n            `coalesce(\"first_name\", \"last_name\", max(\"last_name\"), '(N/A)') as \"name\"`,\n            'from \"person\"',\n            'group by \"first_name\", \"last_name\"',\n          ],\n          parameters: [],\n        },\n        sqlite: {\n          sql: [\n            'select',\n            `coalesce(\"first_name\", \"last_name\", max(\"last_name\"), '(N/A)') as \"name\"`,\n            'from \"person\"',\n            'group by \"first_name\", \"last_name\"',\n          ],\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/controlled-transaction.test.ts",
    "content": "import * as sinon from 'sinon'\nimport { Connection, ISOLATION_LEVEL } from 'tedious'\nimport {\n  CompiledQuery,\n  ControlledTransaction,\n  Driver,\n  DummyDriver,\n  Kysely,\n  SqliteDialect,\n  TRANSACTION_ACCESS_MODES,\n} from '../../../'\nimport {\n  DIALECTS,\n  Database,\n  TestContext,\n  clearDatabase,\n  destroyTest,\n  expect,\n  initTest,\n  insertDefaultDataSet,\n  limit,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: controlled transaction`, () => {\n    let ctx: TestContext\n    const executedQueries: CompiledQuery[] = []\n    const sandbox = sinon.createSandbox()\n    let tediousBeginTransactionSpy: sinon.SinonSpy<\n      Parameters<Connection['beginTransaction']>,\n      ReturnType<Connection['beginTransaction']>\n    >\n    let tediousCommitTransactionSpy: sinon.SinonSpy<\n      Parameters<Connection['commitTransaction']>,\n      ReturnType<Connection['commitTransaction']>\n    >\n    let tediousRollbackTransactionSpy: sinon.SinonSpy<\n      Parameters<Connection['rollbackTransaction']>,\n      ReturnType<Connection['rollbackTransaction']>\n    >\n    let tediousSaveTransactionSpy: sinon.SinonSpy<\n      Parameters<Connection['saveTransaction']>,\n      ReturnType<Connection['saveTransaction']>\n    >\n\n    before(async function () {\n      ctx = await initTest(this, dialect, {\n        log(event) {\n          if (event.level === 'query') {\n            executedQueries.push(event.query)\n          }\n        },\n      })\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n      executedQueries.length = 0\n      tediousBeginTransactionSpy = sandbox.spy(\n        Connection.prototype,\n        'beginTransaction',\n      )\n      tediousCommitTransactionSpy = sandbox.spy(\n        Connection.prototype,\n        'commitTransaction',\n      )\n      tediousRollbackTransactionSpy = sandbox.spy(\n        Connection.prototype,\n        'rollbackTransaction',\n      )\n      tediousSaveTransactionSpy = sandbox.spy(\n        Connection.prototype,\n        'saveTransaction',\n      )\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n      sandbox.restore()\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should be able to start and commit a transaction', async () => {\n      const trx = await ctx.db.startTransaction().execute()\n\n      await insertSomething(trx)\n\n      await trx.commit().execute()\n\n      if (dialect == 'postgres') {\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          {\n            sql: 'begin',\n            parameters: [],\n          },\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          { sql: 'commit', parameters: [] },\n        ])\n      } else if (dialect === 'mysql') {\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          {\n            sql: 'begin',\n            parameters: [],\n          },\n          {\n            sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          { sql: 'commit', parameters: [] },\n        ])\n      } else if (dialect === 'mssql') {\n        expect(tediousBeginTransactionSpy.calledOnce).to.be.true\n        expect(tediousBeginTransactionSpy.getCall(0).args[1]).to.be.undefined\n        expect(tediousBeginTransactionSpy.getCall(0).args[2]).to.be.undefined\n\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n        ])\n\n        expect(tediousCommitTransactionSpy.calledOnce).to.be.true\n      } else {\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          {\n            sql: 'begin',\n            parameters: [],\n          },\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          { sql: 'commit', parameters: [] },\n        ])\n      }\n    })\n\n    it('should be able to start and rollback a transaction', async () => {\n      const trx = await ctx.db.startTransaction().execute()\n\n      await insertSomething(trx)\n\n      await trx.rollback().execute()\n\n      if (dialect == 'postgres') {\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          {\n            sql: 'begin',\n            parameters: [],\n          },\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          { sql: 'rollback', parameters: [] },\n        ])\n      } else if (dialect === 'mysql') {\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          {\n            sql: 'begin',\n            parameters: [],\n          },\n          {\n            sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          { sql: 'rollback', parameters: [] },\n        ])\n      } else if (dialect === 'mssql') {\n        expect(tediousBeginTransactionSpy.calledOnce).to.be.true\n        expect(tediousBeginTransactionSpy.getCall(0).args[1]).to.be.undefined\n        expect(tediousBeginTransactionSpy.getCall(0).args[2]).to.be.undefined\n\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n        ])\n\n        expect(tediousRollbackTransactionSpy.calledOnce).to.be.true\n      } else {\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          {\n            sql: 'begin',\n            parameters: [],\n          },\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          { sql: 'rollback', parameters: [] },\n        ])\n      }\n\n      const person = await ctx.db\n        .selectFrom('person')\n        .where('first_name', '=', 'Foo')\n        .select('first_name')\n        .executeTakeFirst()\n\n      expect(person).to.be.undefined\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql') {\n      for (const accessMode of TRANSACTION_ACCESS_MODES) {\n        it(`should set the transaction access mode as \"${accessMode}\"`, async () => {\n          const trx = await ctx.db\n            .startTransaction()\n            .setAccessMode(accessMode)\n            .execute()\n\n          await trx.selectFrom('person').selectAll().execute()\n\n          await trx.commit().execute()\n\n          expect(\n            executedQueries.map((it) => ({\n              sql: it.sql,\n              parameters: it.parameters,\n            })),\n          ).to.eql(\n            {\n              postgres: [\n                { sql: `start transaction ${accessMode}`, parameters: [] },\n                { sql: 'select * from \"person\"', parameters: [] },\n                { sql: 'commit', parameters: [] },\n              ],\n              mysql: [\n                { sql: `set transaction ${accessMode}`, parameters: [] },\n                { sql: 'begin', parameters: [] },\n                { sql: 'select * from `person`', parameters: [] },\n                { sql: 'commit', parameters: [] },\n              ],\n            }[dialect],\n          )\n        })\n      }\n    }\n\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') {\n      for (const isolationLevel of [\n        'read uncommitted',\n        'read committed',\n        'repeatable read',\n        'serializable',\n        ...(dialect === 'mssql' ? (['snapshot'] as const) : []),\n      ] as const) {\n        it(`should set the transaction isolation level as \"${isolationLevel}\"`, async () => {\n          const trx = await ctx.db\n            .startTransaction()\n            .setIsolationLevel(isolationLevel)\n            .execute()\n\n          await insertSomething(trx)\n\n          await trx.commit().execute()\n\n          if (dialect === 'mssql') {\n            expect(tediousBeginTransactionSpy.calledOnce).to.be.true\n            expect(tediousBeginTransactionSpy.getCall(0).args[1]).to.not.be\n              .undefined\n            expect(tediousBeginTransactionSpy.getCall(0).args[2]).to.equal(\n              ISOLATION_LEVEL[\n                isolationLevel.replace(' ', '_').toUpperCase() as any\n              ],\n            )\n            expect(tediousCommitTransactionSpy.calledOnce).to.be.true\n          }\n\n          expect(\n            executedQueries.map((it) => ({\n              sql: it.sql,\n              parameters: it.parameters,\n            })),\n          ).to.eql(\n            {\n              postgres: [\n                {\n                  sql: `start transaction isolation level ${isolationLevel}`,\n                  parameters: [],\n                },\n                {\n                  sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n                  parameters: ['Foo', 'Barson', 'male'],\n                },\n                { sql: 'commit', parameters: [] },\n              ],\n              mysql: [\n                {\n                  sql: `set transaction isolation level ${isolationLevel}`,\n                  parameters: [],\n                },\n                { sql: 'begin', parameters: [] },\n                {\n                  sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n                  parameters: ['Foo', 'Barson', 'male'],\n                },\n                { sql: 'commit', parameters: [] },\n              ],\n              mssql: [\n                {\n                  sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3)',\n                  parameters: ['Foo', 'Barson', 'male'],\n                },\n              ],\n            }[dialect],\n          )\n        })\n      }\n    }\n\n    it('should be able to start a transaction with a single connection', async () => {\n      await ctx.db.connection().execute(async (conn) => {\n        const trx = await conn.startTransaction().execute()\n\n        await insertSomething(trx)\n\n        await trx.commit().execute()\n\n        await insertSomethingElse(conn)\n\n        const trx2 = await conn.startTransaction().execute()\n\n        await insertSomething(trx2)\n\n        await trx2.rollback().execute()\n\n        await insertSomethingElse(conn)\n      })\n\n      const results = await ctx.db\n        .selectFrom('person')\n        .select('first_name')\n        .orderBy('id', 'desc')\n        .$call(limit(3, dialect))\n        .execute()\n      expect(results).to.eql([\n        { first_name: 'Fizz' },\n        { first_name: 'Fizz' },\n        { first_name: 'Foo' },\n      ])\n    })\n\n    it('should be able to savepoint and rollback to savepoint', async () => {\n      const trx = await ctx.db.startTransaction().execute()\n\n      await insertSomething(trx)\n\n      const trxAfterFoo = await trx.savepoint('foo').execute()\n\n      await insertSomethingElse(trxAfterFoo)\n\n      await trxAfterFoo.rollbackToSavepoint('foo').execute()\n\n      await trxAfterFoo.commit().execute()\n\n      if (dialect == 'postgres') {\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          { sql: 'begin', parameters: [] },\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          { sql: 'savepoint \"foo\"', parameters: [] },\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n            parameters: ['Fizz', 'Buzzson', 'female'],\n          },\n          { sql: 'rollback to \"foo\"', parameters: [] },\n          { sql: 'commit', parameters: [] },\n        ])\n      } else if (dialect === 'mysql') {\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          { sql: 'begin', parameters: [] },\n          {\n            sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          { sql: 'savepoint `foo`', parameters: [] },\n          {\n            sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n            parameters: ['Fizz', 'Buzzson', 'female'],\n          },\n          { sql: 'rollback to `foo`', parameters: [] },\n          { sql: 'commit', parameters: [] },\n        ])\n      } else if (dialect === 'mssql') {\n        expect(tediousBeginTransactionSpy.calledOnce).to.be.true\n        expect(tediousBeginTransactionSpy.getCall(0).args[1]).to.be.undefined\n        expect(tediousBeginTransactionSpy.getCall(0).args[2]).to.be.undefined\n\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3)',\n            parameters: ['Fizz', 'Buzzson', 'female'],\n          },\n        ])\n\n        expect(tediousSaveTransactionSpy.calledOnce).to.be.true\n        expect(tediousSaveTransactionSpy.getCall(0).args[1]).to.equal('foo')\n\n        expect(tediousRollbackTransactionSpy.calledOnce).to.be.true\n        expect(tediousRollbackTransactionSpy.getCall(0).args[1]).to.equal('foo')\n\n        expect(tediousCommitTransactionSpy.calledOnce).to.be.true\n      } else {\n        expect(\n          executedQueries.map((it) => ({\n            sql: it.sql,\n            parameters: it.parameters,\n          })),\n        ).to.eql([\n          { sql: 'begin', parameters: [] },\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)',\n            parameters: ['Foo', 'Barson', 'male'],\n          },\n          { sql: 'savepoint \"foo\"', parameters: [] },\n          {\n            sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)',\n            parameters: ['Fizz', 'Buzzson', 'female'],\n          },\n          { sql: 'rollback to \"foo\"', parameters: [] },\n          { sql: 'commit', parameters: [] },\n        ])\n      }\n\n      const results = await ctx.db\n        .selectFrom('person')\n        .where('first_name', 'in', ['Foo', 'Fizz'])\n        .select('first_name')\n        .execute()\n\n      expect(results).to.have.length(1)\n      expect(results[0].first_name).to.equal('Foo')\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') {\n      it('should be able to savepoint and release savepoint', async () => {\n        const trx = await ctx.db.startTransaction().execute()\n\n        await insertSomething(trx)\n\n        const trxAfterFoo = await trx.savepoint('foo').execute()\n\n        await insertSomethingElse(trxAfterFoo)\n\n        await trxAfterFoo.releaseSavepoint('foo').execute()\n\n        await trxAfterFoo.commit().execute()\n\n        if (dialect == 'postgres') {\n          expect(\n            executedQueries.map((it) => ({\n              sql: it.sql,\n              parameters: it.parameters,\n            })),\n          ).to.eql([\n            { sql: 'begin', parameters: [] },\n            {\n              sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n              parameters: ['Foo', 'Barson', 'male'],\n            },\n            { sql: 'savepoint \"foo\"', parameters: [] },\n            {\n              sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n              parameters: ['Fizz', 'Buzzson', 'female'],\n            },\n            { sql: 'release \"foo\"', parameters: [] },\n            { sql: 'commit', parameters: [] },\n          ])\n        } else if (dialect === 'mysql') {\n          expect(\n            executedQueries.map((it) => ({\n              sql: it.sql,\n              parameters: it.parameters,\n            })),\n          ).to.eql([\n            { sql: 'begin', parameters: [] },\n            {\n              sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n              parameters: ['Foo', 'Barson', 'male'],\n            },\n            { sql: 'savepoint `foo`', parameters: [] },\n            {\n              sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n              parameters: ['Fizz', 'Buzzson', 'female'],\n            },\n            { sql: 'release savepoint `foo`', parameters: [] },\n            { sql: 'commit', parameters: [] },\n          ])\n        } else {\n          expect(\n            executedQueries.map((it) => ({\n              sql: it.sql,\n              parameters: it.parameters,\n            })),\n          ).to.eql([\n            { sql: 'begin', parameters: [] },\n            {\n              sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)',\n              parameters: ['Foo', 'Barson', 'male'],\n            },\n            { sql: 'savepoint \"foo\"', parameters: [] },\n            {\n              sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)',\n              parameters: ['Fizz', 'Buzzson', 'female'],\n            },\n            { sql: 'release \"foo\"', parameters: [] },\n            { sql: 'commit', parameters: [] },\n          ])\n        }\n\n        const results = await ctx.db\n          .selectFrom('person')\n          .where('first_name', 'in', ['Foo', 'Fizz'])\n          .select('first_name')\n          .orderBy('first_name')\n          .execute()\n\n        expect(results).to.have.length(2)\n        expect(results[0].first_name).to.equal('Fizz')\n        expect(results[1].first_name).to.equal('Foo')\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should throw an error when trying to release a savepoint as it is not supported', async () => {\n        const trx = await ctx.db.startTransaction().execute()\n\n        await expect(\n          trx.releaseSavepoint('foo' as never).execute(),\n        ).to.be.rejectedWith(\n          'The `releaseSavepoint` method is not supported by this driver',\n        )\n\n        await trx.rollback().execute()\n      })\n    }\n\n    it('should throw an error when trying to execute a query after the transaction has been committed', async () => {\n      const trx = await ctx.db.startTransaction().execute()\n\n      await insertSomething(trx)\n\n      await trx.commit().execute()\n\n      await expect(insertSomethingElse(trx)).to.be.rejectedWith(\n        'Transaction is already committed',\n      )\n    })\n\n    it('should throw an error when trying to execute a query after the transaction has been rolled back', async () => {\n      const trx = await ctx.db.startTransaction().execute()\n\n      await insertSomething(trx)\n\n      await trx.rollback().execute()\n\n      await expect(insertSomethingElse(trx)).to.be.rejectedWith(\n        'Transaction is already rolled back',\n      )\n    })\n  })\n}\n\ndescribe('custom dialect: controlled transaction', () => {\n  const db = new Kysely<Database>({\n    dialect: new (class extends SqliteDialect {\n      createDriver(): Driver {\n        const driver = class extends DummyDriver {}\n\n        // @ts-ignore\n        driver.prototype.releaseSavepoint = undefined\n        // @ts-ignore\n        driver.prototype.rollbackToSavepoint = undefined\n        // @ts-ignore\n        driver.prototype.savepoint = undefined\n\n        return new driver()\n      }\n      // @ts-ignore\n    })({}),\n  })\n  let trx: ControlledTransaction<Database>\n\n  before(async () => {\n    trx = await db.startTransaction().execute()\n  })\n\n  after(async () => {\n    await trx.rollback().execute()\n  })\n\n  it('should throw an error when trying to savepoint on a dialect that does not support it', async () => {\n    const trx = await db.startTransaction().execute()\n\n    await expect(trx.savepoint('foo').execute()).to.be.rejectedWith(\n      'The `savepoint` method is not supported by this driver',\n    )\n  })\n\n  it('should throw an error when trying to rollback to a savepoint on a dialect that does not support it', async () => {\n    const trx = await db.startTransaction().execute()\n\n    await expect(\n      trx.rollbackToSavepoint('foo' as never).execute(),\n    ).to.be.rejectedWith(\n      'The `rollbackToSavepoint` method is not supported by this driver',\n    )\n  })\n\n  it('should throw an error when trying to release a savepoint on a dialect that does not support it', async () => {\n    const trx = await db.startTransaction().execute()\n\n    await expect(\n      trx.releaseSavepoint('foo' as never).execute(),\n    ).to.be.rejectedWith(\n      'The `releaseSavepoint` method is not supported by this driver',\n    )\n  })\n})\n\nasync function insertSomething(db: Kysely<Database>) {\n  return await db\n    .insertInto('person')\n    .values({\n      first_name: 'Foo',\n      last_name: 'Barson',\n      gender: 'male',\n    })\n    .executeTakeFirstOrThrow()\n}\n\nasync function insertSomethingElse(db: Kysely<Database>) {\n  return await db\n    .insertInto('person')\n    .values({\n      first_name: 'Fizz',\n      last_name: 'Buzzson',\n      gender: 'female',\n    })\n    .executeTakeFirstOrThrow()\n}\n"
  },
  {
    "path": "test/node/src/deduplicate-joins.test.ts",
    "content": "import { DeduplicateJoinsPlugin } from '../../..'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  insertDefaultDataSet,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: deduplicate joins`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should remove simple duplicate joins', async () => {\n      const query = ctx.db\n        .withPlugin(new DeduplicateJoinsPlugin())\n        .selectFrom('person')\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select from `person` inner join `pet` on `pet`.`owner_id` = `person`.`id`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"',\n          parameters: [],\n        },\n      })\n    })\n\n    it('should remove complex duplicate joins', async () => {\n      const query = ctx.db\n        .withPlugin(new DeduplicateJoinsPlugin())\n        .selectFrom('person')\n        .innerJoin(\n          ctx.db\n            .selectFrom('pet')\n            .select(['owner_id', 'id as pet_id', 'species'])\n            .as('p'),\n          (join) =>\n            join\n              .onRef('p.owner_id', '=', 'person.id')\n              .on('p.species', 'in', ['cat', 'hamster']),\n        )\n        .innerJoin(\n          ctx.db\n            .selectFrom('pet')\n            .select(['owner_id', 'id as pet_id', 'species'])\n            .as('p'),\n          (join) =>\n            join\n              .onRef('p.owner_id', '=', 'person.id')\n              .on('p.species', 'in', ['cat', 'hamster']),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select from \"person\" inner join (select \"owner_id\", \"id\" as \"pet_id\", \"species\" from \"pet\") as \"p\" on \"p\".\"owner_id\" = \"person\".\"id\" and \"p\".\"species\" in ($1, $2)',\n          parameters: ['cat', 'hamster'],\n        },\n        mysql: {\n          sql: 'select from `person` inner join (select `owner_id`, `id` as `pet_id`, `species` from `pet`) as `p` on `p`.`owner_id` = `person`.`id` and `p`.`species` in (?, ?)',\n          parameters: ['cat', 'hamster'],\n        },\n        mssql: {\n          sql: 'select from \"person\" inner join (select \"owner_id\", \"id\" as \"pet_id\", \"species\" from \"pet\") as \"p\" on \"p\".\"owner_id\" = \"person\".\"id\" and \"p\".\"species\" in (@1, @2)',\n          parameters: ['cat', 'hamster'],\n        },\n        sqlite: {\n          sql: 'select from \"person\" inner join (select \"owner_id\", \"id\" as \"pet_id\", \"species\" from \"pet\") as \"p\" on \"p\".\"owner_id\" = \"person\".\"id\" and \"p\".\"species\" in (?, ?)',\n          parameters: ['cat', 'hamster'],\n        },\n      })\n    })\n\n    it('should not remove non-identical joins', async () => {\n      const query = ctx.db\n        .withPlugin(new DeduplicateJoinsPlugin())\n        .selectFrom('person')\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n        .innerJoin('toy', 'toy.pet_id', 'pet.id')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select from `person` inner join `pet` on `pet`.`owner_id` = `person`.`id` inner join `toy` on `toy`.`pet_id` = `pet`.`id`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\"',\n          parameters: [],\n        },\n      })\n    })\n\n    it('should preserve order of joins', async () => {\n      const query = ctx.db\n        .withPlugin(new DeduplicateJoinsPlugin())\n        .selectFrom('person')\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n        .innerJoin('toy', 'toy.pet_id', 'pet.id')\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select from `person` inner join `pet` on `pet`.`owner_id` = `person`.`id` inner join `toy` on `toy`.`pet_id` = `pet`.`id`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\"',\n          parameters: [],\n        },\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/delete.test.ts",
    "content": "import { DeleteResult, sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  NOT_SUPPORTED,\n  insertDefaultDataSet,\n  DEFAULT_DATA_SET,\n  DIALECTS,\n  Species,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: delete`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should delete one row', async () => {\n      const query = ctx.db.deleteFrom('person').where('gender', '=', 'female')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'delete from \"person\" where \"gender\" = $1',\n          parameters: ['female'],\n        },\n        mysql: {\n          sql: 'delete from `person` where `gender` = ?',\n          parameters: ['female'],\n        },\n        mssql: {\n          sql: 'delete from \"person\" where \"gender\" = @1',\n          parameters: ['female'],\n        },\n        sqlite: {\n          sql: 'delete from \"person\" where \"gender\" = ?',\n          parameters: ['female'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(DeleteResult)\n      expect(result.numDeletedRows).to.equal(1n)\n\n      expect(\n        await ctx.db\n          .selectFrom('person')\n          .select(['first_name', 'last_name', 'gender'])\n          .orderBy('first_name')\n          .orderBy('last_name')\n          .execute(),\n      ).to.eql([\n        { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' },\n        { first_name: 'Sylvester', last_name: 'Stallone', gender: 'male' },\n      ])\n    })\n\n    it('should delete two rows', async () => {\n      const query = ctx.db\n        .deleteFrom('person')\n        .where((eb) =>\n          eb.or([\n            eb('first_name', '=', 'Jennifer'),\n            eb('first_name', '=', 'Arnold'),\n          ]),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'delete from \"person\" where (\"first_name\" = $1 or \"first_name\" = $2)',\n          parameters: ['Jennifer', 'Arnold'],\n        },\n        mysql: {\n          sql: 'delete from `person` where (`first_name` = ? or `first_name` = ?)',\n          parameters: ['Jennifer', 'Arnold'],\n        },\n        mssql: {\n          sql: 'delete from \"person\" where (\"first_name\" = @1 or \"first_name\" = @2)',\n          parameters: ['Jennifer', 'Arnold'],\n        },\n        sqlite: {\n          sql: 'delete from \"person\" where (\"first_name\" = ? or \"first_name\" = ?)',\n          parameters: ['Jennifer', 'Arnold'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(DeleteResult)\n      expect(result.numDeletedRows).to.equal(2n)\n    })\n\n    it('should delete zero rows', async () => {\n      const query = ctx.db\n        .deleteFrom('person')\n        .where('first_name', '=', 'Nobody')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'delete from \"person\" where \"first_name\" = $1',\n          parameters: ['Nobody'],\n        },\n        mysql: {\n          sql: 'delete from `person` where `first_name` = ?',\n          parameters: ['Nobody'],\n        },\n        mssql: {\n          sql: 'delete from \"person\" where \"first_name\" = @1',\n          parameters: ['Nobody'],\n        },\n        sqlite: {\n          sql: 'delete from \"person\" where \"first_name\" = ?',\n          parameters: ['Nobody'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(DeleteResult)\n      expect(result.numDeletedRows).to.equal(0n)\n    })\n\n    if (dialect === 'mysql') {\n      it('should order and limit the deleted rows', async () => {\n        const query = ctx.db.deleteFrom('person').orderBy('first_name').limit(2)\n\n        testSql(query, dialect, {\n          mysql: {\n            sql: 'delete from `person` order by `first_name` limit ?',\n            parameters: [2],\n          },\n          postgres: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(DeleteResult)\n        expect(result.numDeletedRows).to.equal(2n)\n      })\n    }\n\n    if (dialect === 'postgres' || dialect === 'sqlite') {\n      it('should return deleted rows when `returning` is used', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .where('gender', '=', 'male')\n          .returning(['first_name', 'last_name as last'])\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'delete from \"person\" where \"gender\" = $1 returning \"first_name\", \"last_name\" as \"last\"',\n            parameters: ['male'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'delete from \"person\" where \"gender\" = ? returning \"first_name\", \"last_name\" as \"last\"',\n            parameters: ['male'],\n          },\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(2)\n        expect(Object.keys(result[0]).sort()).to.eql(['first_name', 'last'])\n        expect(result).to.containSubset([\n          { first_name: 'Arnold', last: 'Schwarzenegger' },\n          { first_name: 'Sylvester', last: 'Stallone' },\n        ])\n      })\n\n      it('conditional returning statement should add optional fields', async () => {\n        const condition = true\n\n        const query = ctx.db\n          .deleteFrom('person')\n          .where('gender', '=', 'female')\n          .returning('first_name')\n          .$if(condition, (qb) => qb.returning('last_name'))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'delete from \"person\" where \"gender\" = $1 returning \"first_name\", \"last_name\"',\n            parameters: ['female'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'delete from \"person\" where \"gender\" = ? returning \"first_name\", \"last_name\"',\n            parameters: ['female'],\n          },\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n        expect(result.last_name).to.equal('Aniston')\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should delete from t1 using t2', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .using('pet')\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .where('pet.species', '=', sql<Species>`${'NO_SUCH_SPECIES'}`)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"person\"',\n              'using \"pet\"',\n              'where \"pet\".\"owner_id\" = \"person\".\"id\"',\n              'and \"pet\".\"species\" = $1',\n            ],\n            parameters: ['NO_SUCH_SPECIES'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t2, t3', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .using(['pet', 'toy'])\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .whereRef('toy.pet_id', '=', 'pet.id')\n          .where('toy.price', '=', 0)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"person\"',\n              'using \"pet\", \"toy\"',\n              'where \"pet\".\"owner_id\" = \"person\".\"id\"',\n              'and \"toy\".\"pet_id\" = \"pet\".\"id\"',\n              'and \"toy\".\"price\" = $1',\n            ],\n            parameters: [0],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t2, t3 returning t2.column', async () => {\n        const query = ctx.db\n          .deleteFrom('toy')\n          .using(['pet', 'person'])\n          .whereRef('toy.pet_id', '=', 'pet.id')\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .where('person.first_name', '=', 'Bob')\n          .returning('pet.name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"toy\"',\n              'using \"pet\", \"person\"',\n              'where \"toy\".\"pet_id\" = \"pet\".\"id\"',\n              'and \"pet\".\"owner_id\" = \"person\".\"id\"',\n              'and \"person\".\"first_name\" = $1',\n              'returning \"pet\".\"name\"',\n            ],\n            parameters: ['Bob'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t2, t3 returning t2.*', async () => {\n        const query = ctx.db\n          .deleteFrom('toy')\n          .using(['pet', 'person'])\n          .whereRef('toy.pet_id', '=', 'pet.id')\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .where('person.first_name', '=', 'Bob')\n          .returningAll('pet')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"toy\"',\n              'using \"pet\", \"person\"',\n              'where \"toy\".\"pet_id\" = \"pet\".\"id\"',\n              'and \"pet\".\"owner_id\" = \"person\".\"id\"',\n              'and \"person\".\"first_name\" = $1',\n              'returning \"pet\".*',\n            ],\n            parameters: ['Bob'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 returning *', async () => {\n        const query = ctx.db\n          .deleteFrom('pet')\n          .where('pet.species', '=', 'cat')\n          .returningAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"pet\"',\n              'where \"pet\".\"species\" = $1',\n              'returning *',\n            ],\n            parameters: ['cat'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t2, t3 returning *', async () => {\n        const query = ctx.db\n          .deleteFrom('toy')\n          .using(['pet', 'person'])\n          .whereRef('toy.pet_id', '=', 'pet.id')\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .where('person.first_name', '=', 'Zoro')\n          .returningAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"toy\"',\n              'using \"pet\", \"person\"',\n              'where \"toy\".\"pet_id\" = \"pet\".\"id\"',\n              'and \"pet\".\"owner_id\" = \"person\".\"id\"',\n              'and \"person\".\"first_name\" = $1',\n              'returning *',\n            ],\n            parameters: ['Zoro'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t2, t3 returning t1.*, t2.*', async () => {\n        const query = ctx.db\n          .deleteFrom('toy')\n          .using(['pet', 'person'])\n          .whereRef('toy.pet_id', '=', 'pet.id')\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .where('person.first_name', '=', 'Luffy')\n          .returningAll(['toy', 'pet'])\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"toy\"',\n              'using \"pet\", \"person\"',\n              'where \"toy\".\"pet_id\" = \"pet\".\"id\"',\n              'and \"pet\".\"owner_id\" = \"person\".\"id\"',\n              'and \"person\".\"first_name\" = $1',\n              'returning \"toy\".*, \"pet\".*',\n            ],\n            parameters: ['Luffy'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t2, t3 returning t2.*', async () => {\n        const query = ctx.db\n          .deleteFrom('toy')\n          .using(['pet', 'person'])\n          .whereRef('toy.pet_id', '=', 'pet.id')\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .where('person.first_name', '=', 'Itachi')\n          .returningAll('pet')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"toy\"',\n              'using \"pet\", \"person\"',\n              'where \"toy\".\"pet_id\" = \"pet\".\"id\"',\n              'and \"pet\".\"owner_id\" = \"person\".\"id\"',\n              'and \"person\".\"first_name\" = $1',\n              'returning \"pet\".*',\n            ],\n            parameters: ['Itachi'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 returning t1.*', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .where('gender', '=', 'male')\n          .returningAll('person')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"person\"',\n              'where \"gender\" = $1',\n              'returning \"person\".*',\n            ],\n            parameters: ['male'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 returning *', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .where('gender', '=', 'male')\n          .returningAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: ['delete from \"person\"', 'where \"gender\" = $1', 'returning *'],\n            parameters: ['male'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t2, t3 returning *', async () => {\n        const query = ctx.db\n          .deleteFrom('toy')\n          .using(['pet', 'person'])\n          .whereRef('toy.pet_id', '=', 'pet.id')\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .where('person.first_name', '=', 'Bob')\n          .returningAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'delete from \"toy\"',\n              'using \"pet\", \"person\"',\n              'where \"toy\".\"pet_id\" = \"pet\".\"id\"',\n              'and \"pet\".\"owner_id\" = \"person\".\"id\"',\n              'and \"person\".\"first_name\" = $1',\n              'returning *',\n            ],\n            parameters: ['Bob'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    if (dialect === 'mysql') {\n      it('should delete from t1 using t1 inner join t2', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .using('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .where('pet.species', '=', sql<Species>`${'NO_SUCH_SPECIES'}`)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`',\n              'using `person`',\n              'inner join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'where `pet`.`species` = ?',\n            ],\n            parameters: ['NO_SUCH_SPECIES'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t1 left join t2', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .using('person')\n          .leftJoin('pet', 'pet.owner_id', 'person.id')\n          .where('pet.species', '=', sql<Species>`${'NO_SUCH_SPECIES'}`)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`',\n              'using `person`',\n              'left join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'where `pet`.`species` = ?',\n            ],\n            parameters: ['NO_SUCH_SPECIES'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t1 inner join t2 left join t3', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .using('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .leftJoin('toy', 'toy.pet_id', 'pet.id')\n          .where(({ eb, or }) =>\n            or([\n              eb('pet.species', '=', sql<Species>`${'NO_SUCH_SPECIES'}`),\n              eb('toy.price', '=', 0),\n            ]),\n          )\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: 'delete from `person` using `person` inner join `pet` on `pet`.`owner_id` = `person`.`id` left join `toy` on `toy`.`pet_id` = `pet`.`id` where (`pet`.`species` = ? or `toy`.`price` = ?)',\n            parameters: ['NO_SUCH_SPECIES', 0],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t1, t2', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .using(['person', 'pet'])\n          .where('pet.species', '=', sql<Species>`${'NO_SUCH_SPECIES'}`)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`',\n              'using `person`, `pet`',\n              'where `pet`.`species` = ?',\n            ],\n            parameters: ['NO_SUCH_SPECIES'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t1, t2 inner join t3', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .using(['person', 'pet'])\n          .innerJoin('toy', 'toy.pet_id', 'pet.id')\n          .where('toy.price', '=', 0)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`',\n              'using `person`, `pet`',\n              'inner join `toy` on `toy`.`pet_id` = `pet`.`id`',\n              'where `toy`.`price` = ?',\n            ],\n            parameters: [0],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1 using t1, t2 left join t3', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .using(['person', 'pet'])\n          .leftJoin('toy', 'toy.pet_id', 'pet.id')\n          .where('toy.price', '=', 0)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`',\n              'using `person`, `pet`',\n              'left join `toy` on `toy`.`pet_id` = `pet`.`id`',\n              'where `toy`.`price` = ?',\n            ],\n            parameters: [0],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1, t2 using t1 inner join t2', async () => {\n        const query = ctx.db\n          .deleteFrom(['person', 'pet'])\n          .using('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .where('person.id', '=', 911)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`, `pet`',\n              'using `person`',\n              'inner join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'where `person`.`id` = ?',\n            ],\n            parameters: [911],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1, t2 using t1 left join t2', async () => {\n        const query = ctx.db\n          .deleteFrom(['person', 'pet'])\n          .using('person')\n          .leftJoin('pet', 'pet.owner_id', 'person.id')\n          .where('person.id', '=', 911)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`, `pet`',\n              'using `person`',\n              'left join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'where `person`.`id` = ?',\n            ],\n            parameters: [911],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1, t2 using t1 inner join t2 inner join t3', async () => {\n        const query = ctx.db\n          .deleteFrom(['person', 'pet'])\n          .using('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .innerJoin('toy', 'toy.pet_id', 'pet.id')\n          .where('toy.price', '=', 1000)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`, `pet`',\n              'using `person`',\n              'inner join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'inner join `toy` on `toy`.`pet_id` = `pet`.`id`',\n              'where `toy`.`price` = ?',\n            ],\n            parameters: [1000],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1, t2 using t1 inner join t2 left join t3', async () => {\n        const query = ctx.db\n          .deleteFrom(['person', 'pet'])\n          .using('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .leftJoin('toy', 'toy.pet_id', 'pet.id')\n          .where('toy.price', '=', 1000)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`, `pet`',\n              'using `person`',\n              'inner join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'left join `toy` on `toy`.`pet_id` = `pet`.`id`',\n              'where `toy`.`price` = ?',\n            ],\n            parameters: [1000],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1, t2 using t1 left join t2 left join t3', async () => {\n        const query = ctx.db\n          .deleteFrom(['person', 'pet'])\n          .using('person')\n          .leftJoin('pet', 'pet.owner_id', 'person.id')\n          .leftJoin('toy', 'toy.pet_id', 'pet.id')\n          .where('toy.price', '=', 1000)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`, `pet`',\n              'using `person`',\n              'left join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'left join `toy` on `toy`.`pet_id` = `pet`.`id`',\n              'where `toy`.`price` = ?',\n            ],\n            parameters: [1000],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1, t2, t3 using t1 inner join t2 inner join t3', async () => {\n        const query = ctx.db\n          .deleteFrom(['person', 'pet', 'toy'])\n          .using('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .innerJoin('toy', 'toy.pet_id', 'pet.id')\n          .where('toy.price', '=', 1000)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`, `pet`, `toy`',\n              'using `person`',\n              'inner join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'inner join `toy` on `toy`.`pet_id` = `pet`.`id`',\n              'where `toy`.`price` = ?',\n            ],\n            parameters: [1000],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1, t2, t3 using t1 inner join t2 left join t3', async () => {\n        const query = ctx.db\n          .deleteFrom(['person', 'pet', 'toy'])\n          .using('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .leftJoin('toy', 'toy.pet_id', 'pet.id')\n          .where('toy.price', '=', 1000)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`, `pet`, `toy`',\n              'using `person`',\n              'inner join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'left join `toy` on `toy`.`pet_id` = `pet`.`id`',\n              'where `toy`.`price` = ?',\n            ],\n            parameters: [1000],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should delete from t1, t2, t3 using t1 left join t2 left join t3', async () => {\n        const query = ctx.db\n          .deleteFrom(['person', 'pet', 'toy'])\n          .using('person')\n          .leftJoin('pet', 'pet.owner_id', 'person.id')\n          .leftJoin('toy', 'toy.pet_id', 'pet.id')\n          .where('toy.price', '=', 1000)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: [\n              'delete from `person`, `pet`, `toy`',\n              'using `person`',\n              'left join `pet` on `pet`.`owner_id` = `person`.`id`',\n              'left join `toy` on `toy`.`pet_id` = `pet`.`id`',\n              'where `toy`.`price` = ?',\n            ],\n            parameters: [1000],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    if (dialect === 'postgres' || dialect === 'mysql') {\n      it('modifyEnd should add arbitrary SQL to the end of the query', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .where('first_name', '=', 'Jennifer')\n          .modifyEnd(sql.raw('-- this is a comment'))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'delete from \"person\" where \"first_name\" = $1 -- this is a comment',\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: 'delete from `person` where `first_name` = ? -- this is a comment',\n            parameters: ['Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(1)\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should delete all rows and stream returned results', async () => {\n        const stream = ctx.db\n          .deleteFrom('person')\n          .returning(['first_name', 'last_name', 'gender'])\n          .stream()\n\n        const people = []\n\n        for await (const person of stream) {\n          people.push(person)\n        }\n\n        expect(people).to.have.length(DEFAULT_DATA_SET.length)\n        expect(people).to.eql(\n          DEFAULT_DATA_SET.map(({ first_name, last_name, gender }) => ({\n            first_name,\n            last_name,\n            gender,\n          })),\n        )\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should delete top', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .top(1)\n          .where('gender', '=', 'male')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'delete top(1) from \"person\" where \"gender\" = @1',\n            parameters: ['male'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(DeleteResult)\n        expect(result.numDeletedRows).to.equal(1n)\n      })\n\n      it('should delete top percent', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .top(50, 'percent')\n          .where('gender', '=', 'male')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'delete top(50) percent from \"person\" where \"gender\" = @1',\n            parameters: ['male'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(DeleteResult)\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should return deleted rows when `output` is used', async () => {\n        const query = ctx.db\n          .deleteFrom('person')\n          .output(['deleted.first_name', 'deleted.last_name as last'])\n          .where('gender', '=', 'male')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'delete from \"person\" output \"deleted\".\"first_name\", \"deleted\".\"last_name\" as \"last\" where \"gender\" = @1',\n            parameters: ['male'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(2)\n        expect(Object.keys(result[0]).sort()).to.eql(['first_name', 'last'])\n        expect(result).to.containSubset([\n          { first_name: 'Arnold', last: 'Schwarzenegger' },\n          { first_name: 'Sylvester', last: 'Stallone' },\n        ])\n      })\n\n      it('conditional `output` statement should add optional fields', async () => {\n        const condition = true\n\n        const query = ctx.db\n          .deleteFrom('person')\n          .output('deleted.first_name')\n          .$if(condition, (qb) => qb.output('deleted.last_name'))\n          .where('gender', '=', 'female')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'delete from \"person\" output \"deleted\".\"first_name\", \"deleted\".\"last_name\" where \"gender\" = @1',\n            parameters: ['female'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n        expect(result.last_name).to.equal('Aniston')\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/disconnects.test.ts",
    "content": "import { Kysely, MssqlDialect, sql } from '../../..'\nimport { DIALECTS, DIALECT_CONFIGS, Database, expect } from './test-setup'\nimport * as tarn from 'tarn'\nimport * as tedious from 'tedious'\n\nconst dialect = 'mssql'\n\nif (DIALECTS.includes(dialect)) {\n  describe(`${dialect}: disconnects`, () => {\n    let connection: tedious.Connection\n    let connectionFactoryTimesCalled = 0\n    let db: Kysely<Database>\n\n    before(() => {\n      db = new Kysely({\n        dialect: new MssqlDialect({\n          tarn: {\n            ...tarn,\n            options: {\n              min: 0,\n              max: 1,\n            },\n          },\n          tedious: {\n            ...tedious,\n            connectionFactory: () => {\n              connectionFactoryTimesCalled++\n\n              return (connection = new tedious.Connection(\n                DIALECT_CONFIGS[dialect],\n              ))\n            },\n          },\n        }),\n      })\n    })\n\n    after(async () => {\n      await db.destroy()\n    })\n\n    it('should be disconnection tolerant', async () => {\n      await sql`select 1`.execute(db)\n      expect(connectionFactoryTimesCalled).to.equal(1)\n\n      connection._onSocketError(new Error('moshe'))\n\n      await sql`select 1`.execute(db)\n      expect(connectionFactoryTimesCalled).to.equal(2)\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/error-stack.test.ts",
    "content": "import { Assertion } from 'chai'\nimport { sql } from '../../../'\n\nimport {\n  destroyTest,\n  initTest,\n  TestContext,\n  expect,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: error stack`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('error stack should contain the userland stack', async () => {\n      for (const query of [\n        ctx.db.selectFrom('person').select(sql`doesnt_exists`.as('d')),\n        ctx.db.updateTable('person').set({ first_name: sql`doesnt_exists` }),\n        ctx.db.deleteFrom('person').where(sql`doesnt_exists`, '=', 1),\n        ctx.db\n          .insertInto('person')\n          .values({ first_name: sql`doesnt_exists`, gender: 'other' }),\n\n        {\n          execute: () => sql`select doesnt_exists`.execute(ctx.db),\n          compile: () => ({ sql: 'select doesnt_exists' }),\n        },\n      ]) {\n        try {\n          await query.execute()\n          expect.fail(\n            `query \"${query.compile().sql}\" was supposed to throw but didn't`,\n          )\n        } catch (err: any) {\n          if (err instanceof Assertion) {\n            throw err\n          }\n\n          const stackLines = err.stack.split('\\n')\n          const lastStackLine = stackLines[stackLines.length - 1]\n          expect(lastStackLine).to.contain(__filename)\n        }\n      }\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/execute.test.ts",
    "content": "import { createSandbox, SinonSpy } from 'sinon'\nimport {\n  CompiledQuery,\n  NoResultError,\n  QueryExecutor,\n  QueryNode,\n} from '../../../'\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  insertPersons,\n  TestContext,\n  expect,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: execute`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertPersons(ctx, [\n        {\n          first_name: 'Jennifer',\n          last_name: 'Aniston',\n          gender: 'female',\n          pets: [\n            { name: 'Catto 1', species: 'cat' },\n            { name: 'Catto 2', species: 'cat' },\n          ],\n        },\n        {\n          first_name: 'Arnold',\n          last_name: 'Schwarzenegger',\n          gender: 'male',\n          pets: [\n            { name: 'Doggo 1', species: 'dog' },\n            { name: 'Doggo 2', species: 'dog' },\n          ],\n        },\n        {\n          first_name: 'Sylvester',\n          last_name: 'Stallone',\n          gender: 'male',\n          pets: [{ name: 'Hammo 1', species: 'hamster' }],\n        },\n      ])\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    describe('executeTakeFirstOrThrow', () => {\n      it('should throw if no result is found', async () => {\n        try {\n          await ctx.db\n            .selectFrom('person')\n            .selectAll('person')\n            .where('id', '=', 99999999)\n            .executeTakeFirstOrThrow()\n\n          throw new Error('should not get here')\n        } catch (error) {\n          expect(error instanceof NoResultError).to.equal(true)\n        }\n      })\n\n      it('should throw a custom error constructor if no result is found and a custom error is provided', async () => {\n        class MyNotFoundError extends Error {\n          node: QueryNode\n\n          constructor(node: QueryNode) {\n            super('custom error')\n            this.node = node\n          }\n        }\n\n        try {\n          await ctx.db\n            .selectFrom('person')\n            .selectAll('person')\n            .where('id', '=', 99999999)\n            .executeTakeFirstOrThrow(MyNotFoundError)\n\n          throw new Error('should not get here')\n        } catch (error) {\n          expect(error instanceof MyNotFoundError).to.equal(true)\n\n          if (error instanceof MyNotFoundError) {\n            expect(error.node.kind).to.equal('SelectQueryNode')\n          }\n        }\n      })\n\n      it('should throw a custom error object if no result is found and a custom error is provided', async () => {\n        const message = 'my custom error'\n        const error = new Error(message)\n\n        try {\n          await ctx.db\n            .selectFrom('person')\n            .selectAll('person')\n            .where('id', '=', 99999999)\n            .executeTakeFirstOrThrow(() => error)\n        } catch (error: any) {\n          expect(error.message).to.equal(message)\n        }\n      })\n    })\n\n    describe('Kysely.executeQuery', () => {\n      const sandbox = createSandbox()\n      let executorSpy: SinonSpy<\n        Parameters<QueryExecutor['executeQuery']>,\n        ReturnType<QueryExecutor['executeQuery']>\n      >\n\n      beforeEach(() => {\n        executorSpy = sandbox.spy(\n          ctx.db.getExecutor() as QueryExecutor,\n          'executeQuery',\n        )\n      })\n\n      afterEach(() => {\n        sandbox.restore()\n      })\n\n      it('should execute a compiled query', async () => {\n        const compiledQuery = CompiledQuery.raw('select 1 as count')\n\n        const results = await ctx.db.executeQuery(compiledQuery)\n\n        expect(executorSpy.calledOnce).to.be.true\n        expect(executorSpy.firstCall.firstArg).to.equal(compiledQuery)\n        expect(results).to.equal(await executorSpy.firstCall.returnValue)\n      })\n\n      it('should compile and execute a query builder', async () => {\n        const query = ctx.db.selectFrom('person').selectAll()\n        const compiledQuery = query.compile()\n\n        const results = await ctx.db.executeQuery(query)\n\n        expect(executorSpy.calledOnce).to.be.true\n        expect(executorSpy.firstCall.firstArg).to.deep.equal(compiledQuery)\n        expect(results).to.equal(await executorSpy.firstCall.returnValue)\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/explain.test.ts",
    "content": "import { expect } from 'chai'\nimport { createSandbox, SinonSpy } from 'sinon'\nimport { DefaultQueryExecutor, sql } from '../../../'\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  insertDefaultDataSet,\n  NOT_SUPPORTED,\n  TestContext,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS.filter((dialect) => dialect !== 'mssql')) {\n  describe(`${dialect}: explain test`, () => {\n    let ctx: TestContext\n    const sandbox = createSandbox()\n    let executeQuerySpy: SinonSpy\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n      executeQuerySpy = sandbox.spy(\n        DefaultQueryExecutor.prototype,\n        'executeQuery',\n      )\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n      sandbox.restore()\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should add explain statement before selects', async () => {\n      await ctx.db.selectFrom('person').selectAll().limit(5).explain()\n\n      expect(executeQuerySpy.calledOnce).to.be.true\n      expect(executeQuerySpy.getCall(0).args[0].sql).to.equal(\n        {\n          postgres: 'explain select * from \"person\" limit $1',\n          mysql: 'explain select * from `person` limit ?',\n          mssql: NOT_SUPPORTED,\n          sqlite: 'explain select * from \"person\" limit ?',\n        }[dialect],\n      )\n    })\n\n    it('should add explain statement before inserts', async () => {\n      await ctx.db.insertInto('person').values({ gender: 'female' }).explain()\n\n      expect(executeQuerySpy.calledOnce).to.be.true\n      expect(executeQuerySpy.getCall(0).args[0].sql).to.equal(\n        {\n          postgres: 'explain insert into \"person\" (\"gender\") values ($1)',\n          mysql: 'explain insert into `person` (`gender`) values (?)',\n          mssql: NOT_SUPPORTED,\n          sqlite: 'explain insert into \"person\" (\"gender\") values (?)',\n        }[dialect],\n      )\n    })\n\n    it('should add explain statement before updates', async () => {\n      await ctx.db\n        .updateTable('person')\n        .set({ gender: 'female' })\n        .where('id', '=', 123)\n        .explain()\n\n      expect(executeQuerySpy.calledOnce).to.be.true\n      expect(executeQuerySpy.getCall(0).args[0].sql).to.equal(\n        {\n          postgres: 'explain update \"person\" set \"gender\" = $1 where \"id\" = $2',\n          mysql: 'explain update `person` set `gender` = ? where `id` = ?',\n          mssql: NOT_SUPPORTED,\n          sqlite: 'explain update \"person\" set \"gender\" = ? where \"id\" = ?',\n        }[dialect],\n      )\n    })\n\n    it('should add explain statement before deletes', async () => {\n      await ctx.db.deleteFrom('person').where('id', '=', 123).explain()\n\n      expect(executeQuerySpy.calledOnce).to.be.true\n      expect(executeQuerySpy.getCall(0).args[0].sql).to.equal(\n        {\n          postgres: 'explain delete from \"person\" where \"id\" = $1',\n          mysql: 'explain delete from `person` where `id` = ?',\n          mssql: NOT_SUPPORTED,\n          sqlite: 'explain delete from \"person\" where \"id\" = ?',\n        }[dialect],\n      )\n    })\n\n    if (dialect === 'mysql') {\n      it('should add explain statement before replaces', async () => {\n        await ctx.db\n          .replaceInto('person')\n          .values({ id: 123, gender: 'female' })\n          .explain()\n\n        expect(executeQuerySpy.calledOnce).to.be.true\n        expect(executeQuerySpy.getCall(0).args[0].sql).to.equal(\n          'explain replace into `person` (`id`, `gender`) values (?, ?)',\n        )\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should add explain statement before select, with analyze', async () => {\n        await ctx.db\n          .selectFrom('person')\n          .where('id', '=', 123)\n          .selectAll()\n          .explain('json', sql`analyze`)\n\n        expect(executeQuerySpy.calledOnce).to.be.true\n        expect(executeQuerySpy.getCall(0).args[0].sql).to.equal(\n          {\n            postgres:\n              'explain (analyze, format json) select * from \"person\" where \"id\" = $1',\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          }[dialect],\n        )\n      })\n    }\n\n    if (dialect === 'mysql') {\n      it('should add explain statement before select, with analyze', async () => {\n        await ctx.db\n          .selectFrom('person')\n          .where('id', '=', 123)\n          .selectAll()\n          .explain('tree', sql`analyze`)\n\n        expect(executeQuerySpy.calledOnce).to.be.true\n        expect(executeQuerySpy.getCall(0).args[0].sql).to.equal(\n          {\n            postgres: NOT_SUPPORTED,\n            mysql:\n              'explain analyze format=tree select * from `person` where `id` = ?',\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          }[dialect],\n        )\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/expression.test.ts",
    "content": "import {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  insertDefaultDataSet,\n  TestContext,\n  testSql,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: expressions`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('expression kitchen sink', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll('person')\n        .where(\n          ({ and, or, eb, fn, exists, not, ref, val, selectFrom, parens }) =>\n            and([\n              or([\n                not(eb('first_name', '=', 'Jennifer')),\n                eb(eb('id', '+', 1), '>', 10),\n                eb(ref('id'), 'in', [10, 20, 30].map(val)),\n                or([eb(fn('upper', ['first_name']), '=', 'SYLVESTER')]),\n                // Empty or\n                or([]),\n              ]),\n              exists(\n                selectFrom('pet')\n                  .select('pet.id')\n                  .whereRef('pet.owner_id', '=', 'person.id'),\n              ),\n              // Empty and\n              and([]),\n              eb('id', '=', 1)\n                .or('id', '=', 2)\n                .or('id', '=', 3)\n                .or(eb('id', '=', 4)),\n              eb('id', '=', 1)\n                .and('first_name', '=', 'Jennifer')\n                .and('last_name', '=', 'Aniston')\n                .and(eb('marital_status', '=', 'divorced')),\n              // Should not produce double parens\n              parens(eb('id', '=', 1).or('id', '=', 2)),\n              eb(parens('id', '+', 1), '>', 10),\n              // Object and\n              eb.and({ first_name: 'Jennifer', last_name: 'Aniston' }),\n              // Object or\n              eb.or({\n                first_name: eb.ref('last_name'),\n                last_name: eb.ref('first_name'),\n              }),\n              // Boolean literal\n              ...(dialect === 'postgres' ||\n              dialect === 'mysql' ||\n              dialect === 'sqlite'\n                ? [eb.lit(true)]\n                : []),\n              // Between expressions\n              eb.between('id', 1000, 2000),\n              ...(dialect === 'postgres'\n                ? [eb.betweenSymmetric('id', 3000, 4000)]\n                : []),\n            ]),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"person\".* from \"person\" where ((not \"first_name\" = $1 or \"id\" + $2 > $3 or \"id\" in ($4, $5, $6) or upper(\"first_name\") = $7 or 1 = 0) and exists (select \"pet\".\"id\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\") and 1 = 1 and (\"id\" = $8 or \"id\" = $9 or \"id\" = $10 or \"id\" = $11) and (\"id\" = $12 and \"first_name\" = $13 and \"last_name\" = $14 and \"marital_status\" = $15) and (\"id\" = $16 or \"id\" = $17) and (\"id\" + $18) > $19 and (\"first_name\" = $20 and \"last_name\" = $21) and (\"first_name\" = \"last_name\" or \"last_name\" = \"first_name\") and true and \"id\" between $22 and $23 and \"id\" between symmetric $24 and $25)',\n          parameters: [\n            'Jennifer',\n            1,\n            10,\n            10,\n            20,\n            30,\n            'SYLVESTER',\n            1,\n            2,\n            3,\n            4,\n            1,\n            'Jennifer',\n            'Aniston',\n            'divorced',\n            1,\n            2,\n            1,\n            10,\n            'Jennifer',\n            'Aniston',\n            1000,\n            2000,\n            3000,\n            4000,\n          ],\n        },\n        mysql: {\n          sql: 'select `person`.* from `person` where ((not `first_name` = ? or `id` + ? > ? or `id` in (?, ?, ?) or upper(`first_name`) = ? or 1 = 0) and exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id`) and 1 = 1 and (`id` = ? or `id` = ? or `id` = ? or `id` = ?) and (`id` = ? and `first_name` = ? and `last_name` = ? and `marital_status` = ?) and (`id` = ? or `id` = ?) and (`id` + ?) > ? and (`first_name` = ? and `last_name` = ?) and (`first_name` = `last_name` or `last_name` = `first_name`) and true and `id` between ? and ?)',\n          parameters: [\n            'Jennifer',\n            1,\n            10,\n            10,\n            20,\n            30,\n            'SYLVESTER',\n            1,\n            2,\n            3,\n            4,\n            1,\n            'Jennifer',\n            'Aniston',\n            'divorced',\n            1,\n            2,\n            1,\n            10,\n            'Jennifer',\n            'Aniston',\n            1000,\n            2000,\n          ],\n        },\n        mssql: {\n          sql: 'select \"person\".* from \"person\" where ((not \"first_name\" = @1 or \"id\" + @2 > @3 or \"id\" in (@4, @5, @6) or upper(\"first_name\") = @7 or 1 = 0) and exists (select \"pet\".\"id\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\") and 1 = 1 and (\"id\" = @8 or \"id\" = @9 or \"id\" = @10 or \"id\" = @11) and (\"id\" = @12 and \"first_name\" = @13 and \"last_name\" = @14 and \"marital_status\" = @15) and (\"id\" = @16 or \"id\" = @17) and (\"id\" + @18) > @19 and (\"first_name\" = @20 and \"last_name\" = @21) and (\"first_name\" = \"last_name\" or \"last_name\" = \"first_name\") and \"id\" between @22 and @23)',\n          parameters: [\n            'Jennifer',\n            1,\n            10,\n            10,\n            20,\n            30,\n            'SYLVESTER',\n            1,\n            2,\n            3,\n            4,\n            1,\n            'Jennifer',\n            'Aniston',\n            'divorced',\n            1,\n            2,\n            1,\n            10,\n            'Jennifer',\n            'Aniston',\n            1000,\n            2000,\n          ],\n        },\n        sqlite: {\n          sql: 'select \"person\".* from \"person\" where ((not \"first_name\" = ? or \"id\" + ? > ? or \"id\" in (?, ?, ?) or upper(\"first_name\") = ? or 1 = 0) and exists (select \"pet\".\"id\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\") and 1 = 1 and (\"id\" = ? or \"id\" = ? or \"id\" = ? or \"id\" = ?) and (\"id\" = ? and \"first_name\" = ? and \"last_name\" = ? and \"marital_status\" = ?) and (\"id\" = ? or \"id\" = ?) and (\"id\" + ?) > ? and (\"first_name\" = ? and \"last_name\" = ?) and (\"first_name\" = \"last_name\" or \"last_name\" = \"first_name\") and true and \"id\" between ? and ?)',\n          parameters: [\n            'Jennifer',\n            1,\n            10,\n            10,\n            20,\n            30,\n            'SYLVESTER',\n            1,\n            2,\n            3,\n            4,\n            1,\n            'Jennifer',\n            'Aniston',\n            'divorced',\n            1,\n            2,\n            1,\n            10,\n            'Jennifer',\n            'Aniston',\n            1000,\n            2000,\n          ],\n        },\n      })\n\n      await query.execute()\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/group-by.test.ts",
    "content": "import { sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  insertDefaultDataSet,\n  NOT_SUPPORTED,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: group by`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('group by one column', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['gender', sql`max(first_name)`.as('max_first_name')])\n        .groupBy('gender')\n        .orderBy('gender')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by \"gender\" order by \"gender\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `gender`, max(first_name) as `max_first_name` from `person` group by `gender` order by `gender`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by \"gender\" order by \"gender\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by \"gender\" order by \"gender\"',\n          parameters: [],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(2)\n      expect(persons).to.containSubset([\n        {\n          max_first_name: 'Jennifer',\n          gender: 'female',\n        },\n        {\n          max_first_name: 'Sylvester',\n          gender: 'male',\n        },\n      ])\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') {\n      it('group by selection', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(['gender as g', sql`max(first_name)`.as('max_first_name')])\n          .groupBy('g')\n          .orderBy('g')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"gender\" as \"g\", max(first_name) as \"max_first_name\" from \"person\" group by \"g\" order by \"g\"',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select `gender` as `g`, max(first_name) as `max_first_name` from `person` group by `g` order by `g`',\n            parameters: [],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'select \"gender\" as \"g\", max(first_name) as \"max_first_name\" from \"person\" group by \"g\" order by \"g\"',\n            parameters: [],\n          },\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(2)\n        expect(persons).to.containSubset([\n          {\n            max_first_name: 'Jennifer',\n            g: 'female',\n          },\n          {\n            max_first_name: 'Sylvester',\n            g: 'male',\n          },\n        ])\n      })\n    }\n\n    it('group by two columns', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['gender', sql`max(first_name)`.as('max_first_name')])\n        .groupBy(['gender', 'id'])\n        .orderBy('gender')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by \"gender\", \"id\" order by \"gender\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `gender`, max(first_name) as `max_first_name` from `person` group by `gender`, `id` order by `gender`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by \"gender\", \"id\" order by \"gender\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by \"gender\", \"id\" order by \"gender\"',\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('group by a reference', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['gender', sql`max(first_name)`.as('max_first_name')])\n        .groupBy('person.gender')\n        .orderBy('gender', 'asc')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by \"person\".\"gender\" order by \"gender\" asc',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `gender`, max(first_name) as `max_first_name` from `person` group by `person`.`gender` order by `gender` asc',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by \"person\".\"gender\" order by \"gender\" asc',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by \"person\".\"gender\" order by \"gender\" asc',\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('group by a raw expression', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['gender', sql`max(first_name)`.as('max_first_name')])\n        .groupBy(sql`person.gender`)\n        .orderBy('gender', 'asc')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by person.gender order by \"gender\" asc',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `gender`, max(first_name) as `max_first_name` from `person` group by person.gender order by `gender` asc',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by person.gender order by \"gender\" asc',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select \"gender\", max(first_name) as \"max_first_name\" from \"person\" group by person.gender order by \"gender\" asc',\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') {\n      it('group by a sub query', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(sql`max(first_name)`.as('max_first_name'))\n          .groupBy((qb) =>\n            qb\n              .selectFrom('pet')\n              .whereRef('person.id', '=', 'pet.owner_id')\n              .select('pet.name'),\n          )\n          .orderBy('max_first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'select max(first_name) as \"max_first_name\"',\n              'from \"person\"',\n              'group by (select \"pet\".\"name\" from \"pet\" where \"person\".\"id\" = \"pet\".\"owner_id\")',\n              'order by \"max_first_name\"',\n            ],\n            parameters: [],\n          },\n          mysql: {\n            sql: [\n              'select max(first_name) as `max_first_name`',\n              'from `person`',\n              'group by (select `pet`.`name` from `pet` where `person`.`id` = `pet`.`owner_id`)',\n              'order by `max_first_name`',\n            ],\n            parameters: [],\n          },\n          mssql: {\n            sql: [\n              'select max(first_name) as \"max_first_name\"',\n              'from \"person\"',\n              'group by (select \"pet\".\"name\" from \"pet\" where \"person\".\"id\" = \"pet\".\"owner_id\")',\n              'order by \"max_first_name\"',\n            ],\n            parameters: [],\n          },\n          sqlite: {\n            sql: [\n              'select max(first_name) as \"max_first_name\"',\n              'from \"person\"',\n              'group by (select \"pet\".\"name\" from \"pet\" where \"person\".\"id\" = \"pet\".\"owner_id\")',\n              'order by \"max_first_name\"',\n            ],\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n    }\n\n    it('conditional group by', async () => {\n      const filterByPetCount = true\n      const { count } = ctx.db.fn\n\n      // Insert another pet for Arnold.\n      await ctx.db\n        .insertInto('pet')\n        .values({\n          name: 'Doggo 2',\n          species: 'dog',\n          owner_id: ctx.db\n            .selectFrom('person')\n            .select('id')\n            .where('first_name', '=', 'Arnold'),\n        })\n        .execute()\n\n      const result = await ctx.db\n        .selectFrom('person')\n        .select('person.first_name')\n        .$if(filterByPetCount, (qb) =>\n          qb\n            .innerJoin('pet', 'pet.owner_id', 'person.id')\n            .having(count('pet.id'), '>', 1)\n            .groupBy('person.first_name'),\n        )\n        .execute()\n\n      expect(result).to.eql([{ first_name: 'Arnold' }])\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/handle-empty-in-lists-plugin.test.ts",
    "content": "import {\n  HandleEmptyInListsPlugin,\n  pushValueIntoList,\n  replaceWithNoncontingentExpression,\n} from '../../../dist/cjs/index.js'\nimport {\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  DIALECTS,\n  insertDefaultDataSet,\n  BuiltInDialect,\n  NOT_SUPPORTED,\n  clearDatabase,\n} from './test-setup.js'\n\nconst fixtures = [\n  {\n    strategy: replaceWithNoncontingentExpression,\n    replaceIn: (_lhs: string) => '1 = 0',\n    inReturnValue: (dialect: BuiltInDialect) =>\n      ({\n        [dialect]: false,\n        mysql: '0',\n        sqlite: 0,\n      })[dialect],\n    replaceNotIn: (_lhs: string) => '1 = 1',\n    notInReturnValue: (dialect: BuiltInDialect) =>\n      ({\n        [dialect]: true,\n        mysql: '1',\n        sqlite: 1,\n      })[dialect],\n  },\n  {\n    strategy: pushValueIntoList('__kysely_no_values_were_provided__'),\n    replaceIn: (lhs: string) => `${lhs} in (null)`,\n    inReturnValue: () => null,\n    replaceNotIn: (lhs: string) =>\n      `cast(${lhs} as char) not in ('__kysely_no_values_were_provided__')`,\n    notInReturnValue: (dialect: BuiltInDialect) =>\n      ({\n        [dialect]: true,\n        mysql: '1',\n        sqlite: 1,\n      })[dialect],\n  },\n] as const\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: handle empty in lists plugin`, () => {\n    for (const fixture of fixtures) {\n      describe(`strategy: ${fixture.strategy.name}`, () => {\n        let ctx: TestContext\n\n        before(async function () {\n          ctx = await initTest(this, dialect, {\n            plugins: [\n              new HandleEmptyInListsPlugin({ strategy: fixture.strategy }),\n            ],\n          })\n        })\n\n        beforeEach(async () => {\n          await insertDefaultDataSet(ctx)\n        })\n\n        afterEach(async () => {\n          await clearDatabase(ctx)\n        })\n\n        after(async () => {\n          await destroyTest(ctx)\n        })\n\n        it('should handle `select ... where {{string_ref}} in ()`', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .where('first_name', 'in', [])\n            .select('first_name')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `select \"first_name\" from \"person\" where ${fixture.replaceIn('\"first_name\"')}`,\n              parameters: [],\n            },\n            mysql: {\n              sql: `select \\`first_name\\` from \\`person\\` where ${fixture.replaceIn('`first_name`')}`,\n              parameters: [],\n            },\n            mssql: {\n              sql: `select \"first_name\" from \"person\" where ${fixture.replaceIn('\"first_name\"')}`,\n              parameters: [],\n            },\n            sqlite: {\n              sql: `select \"first_name\" from \"person\" where ${fixture.replaceIn('\"first_name\"')}`,\n              parameters: [],\n            },\n          })\n\n          const result = await query.execute()\n\n          expect(result).to.have.lengthOf(0)\n        })\n\n        it('should handle `select ... where {{string_ref}} not in ()`', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .where('first_name', 'not in', [])\n            .select('first_name')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `select \"first_name\" from \"person\" where ${fixture.replaceNotIn('\"first_name\"')}`,\n              parameters: [],\n            },\n            mysql: {\n              sql: `select \\`first_name\\` from \\`person\\` where ${fixture.replaceNotIn('`first_name`')}`,\n              parameters: [],\n            },\n            mssql: {\n              sql: `select \"first_name\" from \"person\" where ${fixture.replaceNotIn('\"first_name\"')}`,\n              parameters: [],\n            },\n            sqlite: {\n              sql: `select \"first_name\" from \"person\" where ${fixture.replaceNotIn('\"first_name\"')}`,\n              parameters: [],\n            },\n          })\n\n          const result = await query.execute()\n\n          expect(result).to.have.lengthOf(3)\n        })\n\n        it('should handle `select ... where {{number_ref}} in ()`', async () => {\n          const result = await ctx.db\n            .selectFrom('person')\n            .where('children', 'in', [])\n            .select('children')\n            .execute()\n\n          expect(result).to.have.lengthOf(0)\n        })\n\n        it('should handle `select ... where {{number_ref}} not in ()`', async () => {\n          const result = await ctx.db\n            .selectFrom('person')\n            .where('children', 'not in', [])\n            .select('children')\n            .execute()\n\n          expect(result).to.have.lengthOf(3)\n        })\n\n        it('should handle `select ... having ... in ()`', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .groupBy('first_name')\n            .having('first_name', 'in', [])\n            .select('first_name')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `select \"first_name\" from \"person\" group by \"first_name\" having ${fixture.replaceIn('\"first_name\"')}`,\n              parameters: [],\n            },\n            mysql: {\n              sql: `select \\`first_name\\` from \\`person\\` group by \\`first_name\\` having ${fixture.replaceIn('`first_name`')}`,\n              parameters: [],\n            },\n            mssql: {\n              sql: `select \"first_name\" from \"person\" group by \"first_name\" having ${fixture.replaceIn('\"first_name\"')}`,\n              parameters: [],\n            },\n            sqlite: {\n              sql: `select \"first_name\" from \"person\" group by \"first_name\" having ${fixture.replaceIn('\"first_name\"')}`,\n              parameters: [],\n            },\n          })\n\n          const result = await query.execute()\n\n          expect(result).to.have.lengthOf(0)\n        })\n\n        it('should handle `select ... having ... not in ()`', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .groupBy('first_name')\n            .having('first_name', 'not in', [])\n            .select('first_name')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `select \"first_name\" from \"person\" group by \"first_name\" having ${fixture.replaceNotIn('\"first_name\"')}`,\n              parameters: [],\n            },\n            mysql: {\n              sql: `select \\`first_name\\` from \\`person\\` group by \\`first_name\\` having ${fixture.replaceNotIn('`first_name`')}`,\n              parameters: [],\n            },\n            mssql: {\n              sql: `select \"first_name\" from \"person\" group by \"first_name\" having ${fixture.replaceNotIn('\"first_name\"')}`,\n              parameters: [],\n            },\n            sqlite: {\n              sql: `select \"first_name\" from \"person\" group by \"first_name\" having ${fixture.replaceNotIn('\"first_name\"')}`,\n              parameters: [],\n            },\n          })\n\n          const result = await query.execute()\n\n          expect(result).to.have.lengthOf(3)\n        })\n\n        if (\n          dialect === 'mysql' ||\n          dialect === 'postgres' ||\n          dialect === 'sqlite'\n        ) {\n          it('should handle `select ... in (), ... not in ()`', async () => {\n            const query = ctx.db\n              .selectFrom('person')\n              .select((eb) => [\n                eb('first_name', 'in', []).as('in'),\n                eb('first_name', 'not in', []).as('not_in'),\n              ])\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: `select ${fixture.replaceIn('\"first_name\"')} as \"in\", ${fixture.replaceNotIn('\"first_name\"')} as \"not_in\" from \"person\"`,\n                parameters: [],\n              },\n              mysql: {\n                sql: `select ${fixture.replaceIn('`first_name`')} as \\`in\\`, ${fixture.replaceNotIn('`first_name`')} as \\`not_in\\` from \\`person\\``,\n                parameters: [],\n              },\n              mssql: NOT_SUPPORTED,\n              sqlite: {\n                sql: `select ${fixture.replaceIn('\"first_name\"')} as \"in\", ${fixture.replaceNotIn('\"first_name\"')} as \"not_in\" from \"person\"`,\n                parameters: [],\n              },\n            })\n\n            const result = await query.execute()\n\n            expect(result).to.deep.equal(\n              new Array(3).fill({\n                in: fixture.inReturnValue(dialect),\n                not_in: fixture.notInReturnValue(dialect),\n              }),\n            )\n          })\n        }\n\n        it('should handle `update ... where ... in ()`', async () => {\n          const query = ctx.db\n            .updateTable('person')\n            .set('first_name', 'Tesla')\n            .where('id', 'in', [])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `update \"person\" set \"first_name\" = $1 where ${fixture.replaceIn('\"id\"')}`,\n              parameters: ['Tesla'],\n            },\n            mysql: {\n              sql: `update \\`person\\` set \\`first_name\\` = ? where ${fixture.replaceIn('`id`')}`,\n              parameters: ['Tesla'],\n            },\n            mssql: {\n              sql: `update \"person\" set \"first_name\" = @1 where ${fixture.replaceIn('\"id\"')}`,\n              parameters: ['Tesla'],\n            },\n            sqlite: {\n              sql: `update \"person\" set \"first_name\" = ? where ${fixture.replaceIn('\"id\"')}`,\n              parameters: ['Tesla'],\n            },\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result.numUpdatedRows).to.equal(0n)\n        })\n\n        it('should handle `update ... where ... not in ()`', async () => {\n          const query = ctx.db\n            .updateTable('person')\n            .set('first_name', 'John')\n            .where('id', 'not in', [])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `update \"person\" set \"first_name\" = $1 where ${fixture.replaceNotIn('\"id\"')}`,\n              parameters: ['John'],\n            },\n            mysql: {\n              sql: `update \\`person\\` set \\`first_name\\` = ? where ${fixture.replaceNotIn('`id`')}`,\n              parameters: ['John'],\n            },\n            mssql: {\n              sql: `update \"person\" set \"first_name\" = @1 where ${fixture.replaceNotIn('\"id\"')}`,\n              parameters: ['John'],\n            },\n            sqlite: {\n              sql: `update \"person\" set \"first_name\" = ? where ${fixture.replaceNotIn('\"id\"')}`,\n              parameters: ['John'],\n            },\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result.numUpdatedRows).to.equal(3n)\n        })\n\n        it('should handle `delete ... where ... in ()`', async () => {\n          const query = ctx.db.deleteFrom('person').where('id', 'in', [])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `delete from \"person\" where ${fixture.replaceIn('\"id\"')}`,\n              parameters: [],\n            },\n            mysql: {\n              sql: `delete from \\`person\\` where ${fixture.replaceIn('`id`')}`,\n              parameters: [],\n            },\n            mssql: {\n              sql: `delete from \"person\" where ${fixture.replaceIn('\"id\"')}`,\n              parameters: [],\n            },\n            sqlite: {\n              sql: `delete from \"person\" where ${fixture.replaceIn('\"id\"')}`,\n              parameters: [],\n            },\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result.numDeletedRows).to.equal(0n)\n        })\n\n        it('should handle `delete ... where ... not in ()`', async () => {\n          const query = ctx.db.deleteFrom('person').where('id', 'not in', [])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `delete from \"person\" where ${fixture.replaceNotIn('\"id\"')}`,\n              parameters: [],\n            },\n            mysql: {\n              sql: `delete from \\`person\\` where ${fixture.replaceNotIn('`id`')}`,\n              parameters: [],\n            },\n            mssql: {\n              sql: `delete from \"person\" where ${fixture.replaceNotIn('\"id\"')}`,\n              parameters: [],\n            },\n            sqlite: {\n              sql: `delete from \"person\" where ${fixture.replaceNotIn('\"id\"')}`,\n              parameters: [],\n            },\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result.numDeletedRows).to.equal(3n)\n        })\n\n        it('should not affect queries with non-empty lists', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .where('first_name', 'in', ['Jennifer'])\n            .select('first_name')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'select \"first_name\" from \"person\" where \"first_name\" in ($1)',\n              parameters: ['Jennifer'],\n            },\n            mysql: {\n              sql: 'select `first_name` from `person` where `first_name` in (?)',\n              parameters: ['Jennifer'],\n            },\n            mssql: {\n              sql: 'select \"first_name\" from \"person\" where \"first_name\" in (@1)',\n              parameters: ['Jennifer'],\n            },\n            sqlite: {\n              sql: 'select \"first_name\" from \"person\" where \"first_name\" in (?)',\n              parameters: ['Jennifer'],\n            },\n          })\n\n          const result = await query.execute()\n\n          expect(result).to.deep.equal([{ first_name: 'Jennifer' }])\n        })\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/having.test.ts",
    "content": "import { sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  insertPersons,\n  TestContext,\n  testSql,\n  expect,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: having`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertPersons(ctx, [\n        {\n          first_name: 'Jennifer',\n          last_name: 'Aniston',\n          gender: 'female',\n          pets: [\n            { name: 'Catto 1', species: 'cat' },\n            { name: 'Catto 2', species: 'cat' },\n          ],\n        },\n        {\n          first_name: 'Arnold',\n          last_name: 'Schwarzenegger',\n          gender: 'male',\n          pets: [\n            { name: 'Doggo 1', species: 'dog' },\n            { name: 'Doggo 2', species: 'dog' },\n          ],\n        },\n        {\n          first_name: 'Sylvester',\n          last_name: 'Stallone',\n          gender: 'male',\n          pets: [{ name: 'Hammo 1', species: 'hamster' }],\n        },\n      ])\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should add a having statement', async () => {\n      const petCount = sql<number | string>`count(pet.id)`\n\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['first_name', petCount.as('num_pets')])\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n        .groupBy('first_name')\n        .having(petCount, '>', 1)\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            `select \"first_name\", count(pet.id) as \"num_pets\"`,\n            `from \"person\"`,\n            `inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n            `group by \"first_name\"`,\n            `having count(pet.id) > $1`,\n          ],\n          parameters: [1],\n        },\n        mysql: {\n          sql: [\n            'select `first_name`, count(pet.id) as `num_pets`',\n            'from `person`',\n            'inner join `pet` on `pet`.`owner_id` = `person`.`id`',\n            'group by `first_name`',\n            'having count(pet.id) > ?',\n          ],\n          parameters: [1],\n        },\n        mssql: {\n          sql: [\n            `select \"first_name\", count(pet.id) as \"num_pets\"`,\n            `from \"person\"`,\n            `inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n            `group by \"first_name\"`,\n            `having count(pet.id) > @1`,\n          ],\n          parameters: [1],\n        },\n        sqlite: {\n          sql: [\n            `select \"first_name\", count(pet.id) as \"num_pets\"`,\n            `from \"person\"`,\n            `inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n            `group by \"first_name\"`,\n            `having count(pet.id) > ?`,\n          ],\n          parameters: [1],\n        },\n      })\n\n      const result = await query.execute()\n      expect(result).to.have.length(2)\n\n      if (dialect === 'mssql' || dialect === 'sqlite') {\n        expect(result).to.containSubset([\n          { first_name: 'Jennifer', num_pets: 2 },\n          { first_name: 'Arnold', num_pets: 2 },\n        ])\n      } else {\n        expect(result).to.containSubset([\n          { first_name: 'Jennifer', num_pets: '2' },\n          { first_name: 'Arnold', num_pets: '2' },\n        ])\n      }\n    })\n\n    it('should use an aggregate function in a having statement', async () => {\n      const { count } = ctx.db.fn\n\n      const query = ctx.db\n        .selectFrom('person')\n        .innerJoin('pet', 'pet.owner_id', 'person.id')\n        .select(['person.id', count<string | number>('pet.id').as('num_pets')])\n        .groupBy('person.id')\n        .having(count('pet.id'), '>', 1)\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            `select \"person\".\"id\", count(\"pet\".\"id\") as \"num_pets\"`,\n            `from \"person\"`,\n            `inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n            `group by \"person\".\"id\"`,\n            `having count(\"pet\".\"id\") > $1`,\n          ],\n          parameters: [1],\n        },\n        mysql: {\n          sql: [\n            'select `person`.`id`, count(`pet`.`id`) as `num_pets`',\n            'from `person`',\n            'inner join `pet` on `pet`.`owner_id` = `person`.`id`',\n            'group by `person`.`id`',\n            'having count(`pet`.`id`) > ?',\n          ],\n          parameters: [1],\n        },\n        mssql: {\n          sql: [\n            `select \"person\".\"id\", count(\"pet\".\"id\") as \"num_pets\"`,\n            `from \"person\"`,\n            `inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n            `group by \"person\".\"id\"`,\n            `having count(\"pet\".\"id\") > @1`,\n          ],\n          parameters: [1],\n        },\n        sqlite: {\n          sql: [\n            `select \"person\".\"id\", count(\"pet\".\"id\") as \"num_pets\"`,\n            `from \"person\"`,\n            `inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n            `group by \"person\".\"id\"`,\n            `having count(\"pet\".\"id\") > ?`,\n          ],\n          parameters: [1],\n        },\n      })\n\n      const result = await query.execute()\n      expect(result).to.have.length(2)\n\n      if (dialect === 'mssql' || dialect === 'sqlite') {\n        expect(result).to.containSubset([{ num_pets: 2 }, { num_pets: 2 }])\n      } else {\n        expect(result).to.containSubset([{ num_pets: '2' }, { num_pets: '2' }])\n      }\n    })\n\n    it('smoke test for all *having* methods', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .groupBy('first_name')\n        .having((eb) =>\n          eb.or([\n            eb('id', 'in', [1, 2, 3]),\n            eb('first_name', '<', 'foo'),\n            eb('first_name', '=', eb.ref('first_name')),\n          ]),\n        )\n        .havingRef('first_name', '=', 'first_name')\n        .having((eb) => eb.not(eb.exists(eb.selectFrom('pet').select('id'))))\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select * from \"person\" group by \"first_name\" having (\"id\" in ($1, $2, $3) or \"first_name\" < $4 or \"first_name\" = \"first_name\") and \"first_name\" = \"first_name\" and not exists (select \"id\" from \"pet\")`,\n          parameters: [1, 2, 3, 'foo'],\n        },\n        mysql: {\n          sql: 'select * from `person` group by `first_name` having (`id` in (?, ?, ?) or `first_name` < ? or `first_name` = `first_name`) and `first_name` = `first_name` and not exists (select `id` from `pet`)',\n          parameters: [1, 2, 3, 'foo'],\n        },\n        mssql: {\n          sql: `select * from \"person\" group by \"first_name\" having (\"id\" in (@1, @2, @3) or \"first_name\" < @4 or \"first_name\" = \"first_name\") and \"first_name\" = \"first_name\" and not exists (select \"id\" from \"pet\")`,\n          parameters: [1, 2, 3, 'foo'],\n        },\n        sqlite: {\n          sql: `select * from \"person\" group by \"first_name\" having (\"id\" in (?, ?, ?) or \"first_name\" < ? or \"first_name\" = \"first_name\") and \"first_name\" = \"first_name\" and not exists (select \"id\" from \"pet\")`,\n          parameters: [1, 2, 3, 'foo'],\n        },\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/immediate-value-plugin.test.ts",
    "content": "import {\n  DummyDriver,\n  Kysely,\n  PostgresAdapter,\n  PostgresIntrospector,\n  PostgresQueryCompiler,\n} from '../../../'\nimport { ImmediateValuePlugin } from '../../../dist/cjs/plugin/immediate-value/immediate-value-plugin.js'\nimport { Database, NOT_SUPPORTED, testSql } from './test-setup.js'\n\ndescribe('ImmediateValuePlugin', () => {\n  let db: Kysely<Database>\n\n  before(async () => {\n    db = new Kysely({\n      dialect: {\n        createAdapter: () => new PostgresAdapter(),\n        createDriver: () => new DummyDriver(),\n        createIntrospector: (db) => new PostgresIntrospector(db),\n        createQueryCompiler: () => new PostgresQueryCompiler(),\n      },\n      plugins: [new ImmediateValuePlugin()],\n    })\n  })\n\n  it('should inject all values into the query string and leave the parameters array empty', () => {\n    const query = db\n      .selectFrom('person')\n      .where('first_name', '=', 'Sylvester')\n      .where('gender', 'in', ['male', 'other'])\n      .selectAll()\n\n    testSql(query, 'postgres', {\n      postgres: {\n        parameters: [],\n        sql: `select * from \"person\" where \"first_name\" = 'Sylvester' and \"gender\" in ('male', 'other')`,\n      },\n      mysql: NOT_SUPPORTED,\n      mssql: NOT_SUPPORTED,\n      sqlite: NOT_SUPPORTED,\n    })\n  })\n})\n"
  },
  {
    "path": "test/node/src/insert.test.ts",
    "content": "import { AliasedRawBuilder, InsertResult, Kysely, sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  Person,\n  Database,\n  NOT_SUPPORTED,\n  insertDefaultDataSet,\n  DIALECTS,\n  limit,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: insert into`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should insert one row', async () => {\n      const query = ctx.db.insertInto('person').values({\n        first_name: 'Foo',\n        last_name: 'Barson',\n        gender: 'other',\n      })\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n          parameters: ['Foo', 'Barson', 'other'],\n        },\n        mysql: {\n          sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n          parameters: ['Foo', 'Barson', 'other'],\n        },\n        mssql: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3)',\n          parameters: ['Foo', 'Barson', 'other'],\n        },\n        sqlite: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)',\n          parameters: ['Foo', 'Barson', 'other'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n      expect(result).to.be.instanceOf(InsertResult)\n      expect(result.numInsertedOrUpdatedRows).to.equal(1n)\n\n      if (dialect === 'postgres' || dialect === 'mssql') {\n        expect(result.insertId).to.be.undefined\n      } else {\n        expect(result.insertId).to.be.a('bigint')\n      }\n\n      expect(await getNewestPerson(ctx.db)).to.eql({\n        first_name: 'Foo',\n        last_name: 'Barson',\n      })\n    })\n\n    it('should insert one row with default values', async () => {\n      const query = ctx.db.insertInto('person').defaultValues()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'insert into \"person\" default values',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'insert into `person` default values',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'insert into \"person\" default values',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'insert into \"person\" default values',\n          parameters: [],\n        },\n      })\n    })\n\n    it('should insert one row with complex values', async () => {\n      const query = ctx.db.insertInto('person').values({\n        first_name: ctx.db\n          .selectFrom('pet')\n          .select(sql<string>`max(name)`.as('max_name')),\n        last_name:\n          dialect === 'sqlite'\n            ? sql`'Bar' || 'son'`\n            : sql`concat('Bar', 'son')`,\n        gender: 'other',\n      })\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ((select max(name) as \"max_name\" from \"pet\"), concat('Bar', 'son'), $1)`,\n          parameters: ['other'],\n        },\n        mysql: {\n          sql: \"insert into `person` (`first_name`, `last_name`, `gender`) values ((select max(name) as `max_name` from `pet`), concat('Bar', 'son'), ?)\",\n          parameters: ['other'],\n        },\n        mssql: {\n          sql: `insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ((select max(name) as \"max_name\" from \"pet\"), concat('Bar', 'son'), @1)`,\n          parameters: ['other'],\n        },\n        sqlite: {\n          sql: `insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ((select max(name) as \"max_name\" from \"pet\"), 'Bar' || 'son', ?)`,\n          parameters: ['other'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n      expect(result).to.be.instanceOf(InsertResult)\n      expect(result.numInsertedOrUpdatedRows).to.equal(1n)\n\n      expect(await getNewestPerson(ctx.db)).to.eql({\n        first_name: 'Hammo',\n        last_name: 'Barson',\n      })\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') {\n      it('should insert one row with expressions', async () => {\n        const query = ctx.db.insertInto('person').values(({ selectFrom }) => ({\n          first_name: selectFrom('pet')\n            .select('name')\n            .where('species', '=', 'dog')\n            .limit(1),\n          gender: 'female',\n        }))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `insert into \"person\" (\"first_name\", \"gender\") values ((select \"name\" from \"pet\" where \"species\" = $1 limit $2), $3)`,\n            parameters: ['dog', 1, 'female'],\n          },\n          mysql: {\n            sql: 'insert into `person` (`first_name`, `gender`) values ((select `name` from `pet` where `species` = ? limit ?), ?)',\n            parameters: ['dog', 1, 'female'],\n          },\n          sqlite: {\n            sql: `insert into \"person\" (\"first_name\", \"gender\") values ((select \"name\" from \"pet\" where \"species\" = ? limit ?), ?)`,\n            parameters: ['dog', 1, 'female'],\n          },\n          mssql: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n        expect(result).to.be.instanceOf(InsertResult)\n        expect(result.numInsertedOrUpdatedRows).to.equal(1n)\n\n        expect(await getNewestPerson(ctx.db)).to.eql({\n          first_name: 'Doggo',\n          last_name: null,\n        })\n      })\n    }\n\n    it('should insert the result of a select query', async () => {\n      const query = ctx.db\n        .insertInto('person')\n        .columns(['first_name', 'gender'])\n        .expression((eb) =>\n          eb.selectFrom('pet').select(['name', eb.val('other').as('gender')]),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'insert into \"person\" (\"first_name\", \"gender\") select \"name\", $1 as \"gender\" from \"pet\"',\n          parameters: ['other'],\n        },\n        mysql: {\n          sql: 'insert into `person` (`first_name`, `gender`) select `name`, ? as `gender` from `pet`',\n          parameters: ['other'],\n        },\n        mssql: {\n          sql: 'insert into \"person\" (\"first_name\", \"gender\") select \"name\", @1 as \"gender\" from \"pet\"',\n          parameters: ['other'],\n        },\n        sqlite: {\n          sql: 'insert into \"person\" (\"first_name\", \"gender\") select \"name\", ? as \"gender\" from \"pet\"',\n          parameters: ['other'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n      expect(result).to.be.instanceOf(InsertResult)\n\n      const { pet_count } = await ctx.db\n        .selectFrom('pet')\n        .select(sql<string | number | bigint>`count(*)`.as('pet_count'))\n        .executeTakeFirstOrThrow()\n\n      expect(result.numInsertedOrUpdatedRows).to.equal(BigInt(pet_count))\n\n      const persons = await ctx.db\n        .selectFrom('person')\n        .select('first_name')\n        .orderBy('first_name')\n        .execute()\n\n      expect(persons.map((it) => it.first_name)).to.eql([\n        'Arnold',\n        'Catto',\n        'Doggo',\n        'Hammo',\n        'Jennifer',\n        'Sylvester',\n      ])\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      it('should insert the result of a values expression', async () => {\n        const query = ctx.db\n          .insertInto('person')\n          .columns(['first_name', 'gender'])\n          .expression(\n            ctx.db\n              .selectFrom(\n                values(\n                  [\n                    { a: 1, b: 'foo' },\n                    { a: 2, b: 'bar' },\n                  ],\n                  't',\n                ),\n              )\n              .select(['t.a', 't.b']),\n          )\n          .$call((qb) =>\n            dialect === 'postgres'\n              ? qb.returning(['first_name', 'gender'])\n              : qb.output(['inserted.first_name', 'inserted.gender']),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'insert into \"person\" (\"first_name\", \"gender\") select \"t\".\"a\", \"t\".\"b\" from (values ($1, $2), ($3, $4)) as t(a, b) returning \"first_name\", \"gender\"',\n            parameters: [1, 'foo', 2, 'bar'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'insert into \"person\" (\"first_name\", \"gender\") output \"inserted\".\"first_name\", \"inserted\".\"gender\" select \"t\".\"a\", \"t\".\"b\" from (values (@1, @2), (@3, @4)) as t(a, b)',\n            parameters: [1, 'foo', 2, 'bar'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(2)\n        expect(result).to.deep.equal([\n          { first_name: '1', gender: 'foo' },\n          { first_name: '2', gender: 'bar' },\n        ])\n      })\n    }\n\n    it('undefined values should be ignored', async () => {\n      const query = ctx.db.insertInto('person').values({\n        id: undefined,\n        first_name: 'Foo',\n        last_name: 'Barson',\n        gender: 'other',\n      })\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n          parameters: ['Foo', 'Barson', 'other'],\n        },\n        mysql: {\n          sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n          parameters: ['Foo', 'Barson', 'other'],\n        },\n        mssql: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3)',\n          parameters: ['Foo', 'Barson', 'other'],\n        },\n        sqlite: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?)',\n          parameters: ['Foo', 'Barson', 'other'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(InsertResult)\n      expect(result.numInsertedOrUpdatedRows).to.equal(1n)\n\n      if (dialect === 'postgres' || dialect === 'mssql') {\n        expect(result.insertId).to.be.undefined\n      } else {\n        expect(result.insertId).to.be.a('bigint')\n      }\n    })\n\n    if (dialect === 'sqlite') {\n      for (const { method, action } of [\n        { method: 'orAbort', action: 'abort' },\n        { method: 'orFail', action: 'fail' },\n        { method: 'orIgnore', action: 'ignore' },\n        { method: 'orReplace', action: 'replace' },\n        { method: 'orRollback', action: 'rollback' },\n      ] as const) {\n        it(`should insert or ${action}`, async () => {\n          const query = ctx.db.insertInto('person')[method]().values({\n            first_name: 'foo',\n            gender: 'other',\n          })\n\n          testSql(query, dialect, {\n            mysql: NOT_SUPPORTED,\n            postgres: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: `insert or ${action} into \"person\" (\"first_name\", \"gender\") values (?, ?)`,\n              parameters: ['foo', 'other'],\n            },\n          })\n\n          await query.execute()\n        })\n      }\n    }\n\n    if (dialect === 'mysql' || dialect == 'sqlite') {\n      it('should insert one row and ignore conflicts using insert ignore', async () => {\n        const [{ id, ...existingPet }] = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .limit(1)\n          .execute()\n\n        const query = ctx.db.insertInto('pet').ignore().values(existingPet)\n\n        testSql(query, dialect, {\n          mysql: {\n            sql: 'insert ignore into `pet` (`name`, `owner_id`, `species`) values (?, ?, ?)',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n            ],\n          },\n          postgres: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'insert or ignore into \"pet\" (\"name\", \"owner_id\", \"species\") values (?, ?, ?)',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n            ],\n          },\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(InsertResult)\n        expect(result.numInsertedOrUpdatedRows).to.equal(0n)\n        if (dialect === 'sqlite') {\n          // SQLite seems to return the last inserted id even if nothing got inserted.\n          expect(result.insertId! > 0n).to.be.equal(true)\n        } else {\n          expect(result.insertId).to.be.undefined\n        }\n      })\n    }\n\n    if (dialect === 'postgres' || dialect === 'sqlite') {\n      it('should insert one row and ignore conflicts using `on conflict do nothing`', async () => {\n        const [{ id, ...existingPet }] = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .limit(1)\n          .execute()\n\n        const query = ctx.db\n          .insertInto('pet')\n          .values(existingPet)\n          .onConflict((oc) => oc.column('name').doNothing())\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'insert into \"pet\" (\"name\", \"owner_id\", \"species\") values ($1, $2, $3) on conflict (\"name\") do nothing',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n            ],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'insert into \"pet\" (\"name\", \"owner_id\", \"species\") values (?, ?, ?) on conflict (\"name\") do nothing',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n            ],\n          },\n          mysql: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(InsertResult)\n        expect(result.numInsertedOrUpdatedRows).to.equal(0n)\n\n        if (dialect === 'sqlite') {\n          // SQLite seems to return the last inserted id even if nothing got inserted.\n          expect(result.insertId! > 0n).to.be.equal(true)\n        } else {\n          expect(result.insertId).to.be.undefined\n        }\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should insert one row and ignore conflicts using `on conflict on constraint do nothing`', async () => {\n        const [{ id, ...existingPet }] = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .limit(1)\n          .execute()\n\n        const query = ctx.db\n          .insertInto('pet')\n          .values(existingPet)\n          .onConflict((oc) => oc.constraint('pet_name_key').doNothing())\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'insert into \"pet\" (\"name\", \"owner_id\", \"species\") values ($1, $2, $3) on conflict on constraint \"pet_name_key\" do nothing',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n            ],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(InsertResult)\n        expect(result.insertId).to.be.undefined\n        expect(result.numInsertedOrUpdatedRows).to.equal(0n)\n      })\n    }\n\n    if (dialect === 'mysql') {\n      it('should update instead of insert on conflict when using onDuplicateKeyUpdate', async () => {\n        const [{ id, ...existingPet }] = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .limit(1)\n          .execute()\n\n        const query = ctx.db\n          .insertInto('pet')\n          .values(existingPet)\n          .onDuplicateKeyUpdate({ species: 'hamster' })\n\n        testSql(query, dialect, {\n          mysql: {\n            sql: 'insert into `pet` (`name`, `owner_id`, `species`) values (?, ?, ?) on duplicate key update `species` = ?',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n              'hamster',\n            ],\n          },\n          postgres: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(InsertResult)\n        expect(result.insertId).to.equal(BigInt(id))\n        expect(result.numInsertedOrUpdatedRows).to.equal(2n)\n\n        const updatedPet = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .where('id', '=', id)\n          .executeTakeFirstOrThrow()\n\n        expect(updatedPet).to.containSubset({\n          name: 'Catto',\n          species: 'hamster',\n        })\n      })\n    }\n\n    if (dialect === 'postgres' || dialect === 'sqlite') {\n      it('should update instead of insert on conflict when using `on conflict do update`', async () => {\n        const [{ id, ...existingPet }] = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .limit(1)\n          .execute()\n\n        const query = ctx.db\n          .insertInto('pet')\n          .values(existingPet)\n          .onConflict((oc) =>\n            oc.columns(['name']).doUpdateSet({ species: 'hamster' }),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'insert into \"pet\" (\"name\", \"owner_id\", \"species\") values ($1, $2, $3) on conflict (\"name\") do update set \"species\" = $4',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n              'hamster',\n            ],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'insert into \"pet\" (\"name\", \"owner_id\", \"species\") values (?, ?, ?) on conflict (\"name\") do update set \"species\" = ?',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n              'hamster',\n            ],\n          },\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(InsertResult)\n        expect(result.numInsertedOrUpdatedRows).to.equal(1n)\n\n        if (dialect === 'postgres') {\n          expect(result.insertId).to.be.undefined\n        } else {\n          expect(result.insertId).to.be.a('bigint')\n        }\n\n        const updatedPet = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .where('id', '=', id)\n          .executeTakeFirstOrThrow()\n\n        expect(updatedPet).to.containSubset({\n          name: 'Catto',\n          species: 'hamster',\n        })\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should update instead of insert on conflict when using `on conflict on constraint do update`', async () => {\n        const [{ id, ...existingPet }] = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .limit(1)\n          .execute()\n\n        const query = ctx.db\n          .insertInto('pet')\n          .values(existingPet)\n          .onConflict((oc) =>\n            oc.constraint('pet_name_key').doUpdateSet({ species: 'hamster' }),\n          )\n          .returningAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'insert into \"pet\" (\"name\", \"owner_id\", \"species\") values ($1, $2, $3) on conflict on constraint \"pet_name_key\" do update set \"species\" = $4 returning *',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n              'hamster',\n            ],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.containSubset({\n          name: 'Catto',\n          species: 'hamster',\n        })\n      })\n\n      it('should update instead of insert on conflict when using `on conflict do update where`', async () => {\n        const [{ id, ...existingPet }] = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .limit(1)\n          .execute()\n\n        const query = ctx.db\n          .insertInto('pet')\n          .values(existingPet)\n          .onConflict((oc) =>\n            oc\n              .column('name')\n              .where('name', '=', 'Catto')\n              .doUpdateSet({\n                species: 'hamster',\n                name: (eb) => eb.ref('excluded.name'),\n              })\n              .where('excluded.name', '!=', 'Doggo'),\n          )\n          .returningAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'insert into \"pet\" (\"name\", \"owner_id\", \"species\") values ($1, $2, $3) on conflict (\"name\") where \"name\" = $4 do update set \"species\" = $5, \"name\" = \"excluded\".\"name\" where \"excluded\".\"name\" != $6 returning *',\n            parameters: [\n              existingPet.name,\n              existingPet.owner_id,\n              existingPet.species,\n              'Catto',\n              'hamster',\n              'Doggo',\n            ],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(1)\n        expect(result[0]).to.containSubset({\n          species: 'hamster',\n          name: 'Catto',\n        })\n      })\n    }\n\n    it('should insert multiple rows', async () => {\n      const query = ctx.db.insertInto('person').values([\n        {\n          first_name: 'Foo',\n          last_name: 'Bar',\n          gender: 'other',\n        },\n        {\n          first_name: 'Baz',\n          last_name: 'Spam',\n          gender: 'other',\n        },\n      ])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3), ($4, $5, $6)',\n          parameters: ['Foo', 'Bar', 'other', 'Baz', 'Spam', 'other'],\n        },\n        mysql: {\n          sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?), (?, ?, ?)',\n          parameters: ['Foo', 'Bar', 'other', 'Baz', 'Spam', 'other'],\n        },\n        mssql: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3), (@4, @5, @6)',\n          parameters: ['Foo', 'Bar', 'other', 'Baz', 'Spam', 'other'],\n        },\n        sqlite: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (?, ?, ?), (?, ?, ?)',\n          parameters: ['Foo', 'Bar', 'other', 'Baz', 'Spam', 'other'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(InsertResult)\n      expect(result.numInsertedOrUpdatedRows).to.equal(2n)\n\n      if (dialect === 'postgres' || dialect === 'mssql') {\n        expect(result.insertId).to.be.undefined\n      } else {\n        expect(result.insertId).to.be.a('bigint')\n      }\n\n      const inserted = await ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .orderBy('id', 'desc')\n        .$call(limit(2, dialect))\n        .execute()\n\n      expect(inserted).to.containSubset([\n        { first_name: 'Foo', last_name: 'Bar', gender: 'other' },\n        { first_name: 'Baz', last_name: 'Spam', gender: 'other' },\n      ])\n    })\n\n    it('should insert multiple rows while falling back to default values in partial rows - missing columns', async () => {\n      const query = ctx.db.insertInto('person').values([\n        {\n          first_name: 'Foo',\n          // last_name is missing on purpose\n          // middle_name is missing on purpose\n          gender: 'other',\n        },\n        {\n          first_name: 'Baz',\n          last_name: 'Spam',\n          middle_name: 'Bo',\n          gender: 'other',\n        },\n      ])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'insert into \"person\" (\"first_name\", \"gender\", \"last_name\", \"middle_name\") values ($1, $2, default, default), ($3, $4, $5, $6)',\n          parameters: ['Foo', 'other', 'Baz', 'other', 'Spam', 'Bo'],\n        },\n        mysql: {\n          sql: 'insert into `person` (`first_name`, `gender`, `last_name`, `middle_name`) values (?, ?, default, default), (?, ?, ?, ?)',\n          parameters: ['Foo', 'other', 'Baz', 'other', 'Spam', 'Bo'],\n        },\n        mssql: {\n          sql: 'insert into \"person\" (\"first_name\", \"gender\", \"last_name\", \"middle_name\") values (@1, @2, default, default), (@3, @4, @5, @6)',\n          parameters: ['Foo', 'other', 'Baz', 'other', 'Spam', 'Bo'],\n        },\n        sqlite: {\n          sql: 'insert into \"person\" (\"first_name\", \"gender\", \"last_name\", \"middle_name\") values (?, ?, null, null), (?, ?, ?, ?)',\n          parameters: ['Foo', 'other', 'Baz', 'other', 'Spam', 'Bo'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should insert multiple rows while falling back to default values in partial rows - undefined columns', async () => {\n      const query = ctx.db.insertInto('person').values([\n        {\n          first_name: 'Foo',\n          last_name: 'Spam',\n          middle_name: 'Bo',\n          gender: 'other',\n        },\n        {\n          first_name: 'Baz',\n          last_name: undefined,\n          middle_name: undefined,\n          gender: 'other',\n        },\n      ])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"middle_name\", \"gender\") values ($1, $2, $3, $4), ($5, default, default, $6)',\n          parameters: ['Foo', 'Spam', 'Bo', 'other', 'Baz', 'other'],\n        },\n        mysql: {\n          sql: 'insert into `person` (`first_name`, `last_name`, `middle_name`, `gender`) values (?, ?, ?, ?), (?, default, default, ?)',\n          parameters: ['Foo', 'Spam', 'Bo', 'other', 'Baz', 'other'],\n        },\n        mssql: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"middle_name\", \"gender\") values (@1, @2, @3, @4), (@5, default, default, @6)',\n          parameters: ['Foo', 'Spam', 'Bo', 'other', 'Baz', 'other'],\n        },\n        sqlite: {\n          sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"middle_name\", \"gender\") values (?, ?, ?, ?), (?, null, null, ?)',\n          parameters: ['Foo', 'Spam', 'Bo', 'other', 'Baz', 'other'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    // https://github.com/kysely-org/kysely/issues/1310\n    it('should insert multiple rows while falling back to default values in partial rows - different shapes edge case issue - issue #1310', async () => {\n      const query = ctx.db.insertInto('person').values([\n        {\n          gender: 'female',\n          marital_status: 'divorced', // <--- only exists here.\n          children: undefined, // <--- always undefined explicitly.\n        },\n        {\n          gender: 'female',\n          children: undefined, // <--- always undefined explicitly.\n        },\n      ])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `insert into \"person\" (\"gender\", \"marital_status\") values ($1, $2), ($3, default)`,\n          parameters: ['female', 'divorced', 'female'],\n        },\n        mysql: {\n          sql: `insert into \\`person\\` (\\`gender\\`, \\`marital_status\\`) values (?, ?), (?, default)`,\n          parameters: ['female', 'divorced', 'female'],\n        },\n        mssql: {\n          sql: `insert into \"person\" (\"gender\", \"marital_status\") values (@1, @2), (@3, default)`,\n          parameters: ['female', 'divorced', 'female'],\n        },\n        sqlite: {\n          sql: `insert into \"person\" (\"gender\", \"marital_status\") values (?, ?), (?, null)`,\n          parameters: ['female', 'divorced', 'female'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should insert multiple rows while falling back to default values in partial rows - undefined/missing columns', async () => {\n      const query = ctx.db.insertInto('person').values([\n        {\n          first_name: 'Foo',\n          // last_name missing on purpose\n          middle_name: 'Bo',\n          gender: 'other',\n        },\n        {\n          first_name: 'Baz',\n          last_name: 'Spam',\n          middle_name: undefined,\n          gender: 'other',\n        },\n      ])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'insert into \"person\" (\"first_name\", \"middle_name\", \"gender\", \"last_name\") values ($1, $2, $3, default), ($4, default, $5, $6)',\n          parameters: ['Foo', 'Bo', 'other', 'Baz', 'other', 'Spam'],\n        },\n        mysql: {\n          sql: 'insert into `person` (`first_name`, `middle_name`, `gender`, `last_name`) values (?, ?, ?, default), (?, default, ?, ?)',\n          parameters: ['Foo', 'Bo', 'other', 'Baz', 'other', 'Spam'],\n        },\n        mssql: {\n          sql: 'insert into \"person\" (\"first_name\", \"middle_name\", \"gender\", \"last_name\") values (@1, @2, @3, default), (@4, default, @5, @6)',\n          parameters: ['Foo', 'Bo', 'other', 'Baz', 'other', 'Spam'],\n        },\n        sqlite: {\n          sql: 'insert into \"person\" (\"first_name\", \"middle_name\", \"gender\", \"last_name\") values (?, ?, ?, null), (?, null, ?, ?)',\n          parameters: ['Foo', 'Bo', 'other', 'Baz', 'other', 'Spam'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres' || dialect === 'sqlite') {\n      it('should insert a row and return data using `returning`', async () => {\n        const result = await ctx.db\n          .insertInto('person')\n          .values({\n            gender: 'other',\n            first_name: ctx.db\n              .selectFrom('person')\n              .select(sql<string>`max(first_name)`.as('max_first_name')),\n            last_name:\n              dialect === 'postgres'\n                ? sql`concat(cast(${'Bar'} as varchar), cast(${'son'} as varchar))`\n                : sql`cast(${'Bar'} as varchar) || cast(${'son'} as varchar)`,\n          })\n          .returning(['first_name', 'last_name', 'gender'])\n          .executeTakeFirst()\n\n        expect(result).to.eql({\n          first_name: 'Sylvester',\n          last_name: 'Barson',\n          gender: 'other',\n        })\n\n        expect(await getNewestPerson(ctx.db)).to.eql({\n          first_name: 'Sylvester',\n          last_name: 'Barson',\n        })\n      })\n\n      it('should insert a row, returning some fields of inserted row and conditionally returning additional fields', async () => {\n        const condition = true\n\n        const query = ctx.db\n          .insertInto('person')\n          .values({\n            first_name: 'Foo',\n            last_name: 'Barson',\n            gender: 'other',\n          })\n          .returning('first_name')\n          .$if(condition, (qb) => qb.returning('last_name'))\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result.last_name).to.equal('Barson')\n      })\n\n      it('should insert a row and return data using `returningAll`', async () => {\n        const result = await ctx.db\n          .insertInto('person')\n          .values({\n            gender: 'other',\n            first_name: ctx.db\n              .selectFrom('person')\n              .select(sql<string>`max(first_name)`.as('max_first_name')),\n            last_name:\n              dialect === 'postgres'\n                ? sql`concat(cast(${'Bar'} as varchar), cast(${'son'} as varchar))`\n                : sql`cast(${'Bar'} as varchar) || cast(${'son'} as varchar)`,\n          })\n          .returningAll()\n          .executeTakeFirst()\n\n        expect(result).to.containSubset({\n          first_name: 'Sylvester',\n          last_name: 'Barson',\n          gender: 'other',\n        })\n\n        expect(await getNewestPerson(ctx.db)).to.eql({\n          first_name: 'Sylvester',\n          last_name: 'Barson',\n        })\n      })\n    }\n\n    if (dialect === 'postgres' || dialect === 'mysql') {\n      it('modifyEnd should add arbitrary SQL to the end of the query', async () => {\n        const query = ctx.db\n          .insertInto('person')\n          .values({\n            gender: 'other',\n          })\n          .modifyEnd(sql.raw('-- this is a comment'))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'insert into \"person\" (\"gender\") values ($1) -- this is a comment',\n            parameters: ['other'],\n          },\n          mysql: {\n            sql: 'insert into `person` (`gender`) values (?) -- this is a comment',\n            parameters: ['other'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(1)\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should insert multiple rows and stream returned results', async () => {\n        const values = [\n          {\n            first_name: 'Moses',\n            last_name: 'Malone',\n            gender: 'male',\n          },\n          {\n            first_name: 'Erykah',\n            last_name: 'Badu',\n            gender: 'female',\n          },\n        ] as const\n\n        const stream = ctx.db\n          .insertInto('person')\n          .values(values)\n          .returning(['first_name', 'last_name', 'gender'])\n          .stream()\n\n        const people = []\n\n        for await (const person of stream) {\n          people.push(person)\n        }\n\n        expect(people).to.have.length(values.length)\n        expect(people).to.eql(values)\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should insert top', async () => {\n        const query = ctx.db\n          .insertInto('person')\n          .top(1)\n          .columns(['first_name', 'gender'])\n          .expression((eb) =>\n            eb.selectFrom('pet').select(['name', eb.val('other').as('gender')]),\n          )\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'insert top(1) into \"person\" (\"first_name\", \"gender\") select \"name\", @1 as \"gender\" from \"pet\"',\n            parameters: ['other'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.executeTakeFirstOrThrow()\n      })\n\n      it('should insert top percent', async () => {\n        const query = ctx.db\n          .insertInto('person')\n          .top(50, 'percent')\n          .columns(['first_name', 'gender'])\n          .expression((eb) =>\n            eb.selectFrom('pet').select(['name', eb.val('other').as('gender')]),\n          )\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'insert top(50) percent into \"person\" (\"first_name\", \"gender\") select \"name\", @1 as \"gender\" from \"pet\"',\n            parameters: ['other'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.executeTakeFirstOrThrow()\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should insert a row and return data using `output`', async () => {\n        const result = await ctx.db\n          .insertInto('person')\n          .output([\n            'inserted.first_name',\n            'inserted.last_name',\n            'inserted.gender',\n          ])\n          .values({\n            gender: 'other',\n            first_name: ctx.db\n              .selectFrom('person')\n              .select(sql<string>`max(first_name)`.as('max_first_name')),\n            last_name: sql`concat(cast(${'Bar'} as varchar), cast(${'son'} as varchar))`,\n          })\n          .executeTakeFirst()\n\n        expect(result).to.eql({\n          first_name: 'Sylvester',\n          last_name: 'Barson',\n          gender: 'other',\n        })\n\n        expect(await getNewestPerson(ctx.db)).to.eql({\n          first_name: 'Sylvester',\n          last_name: 'Barson',\n        })\n      })\n\n      it('should insert a row, returning some fields of inserted row and conditionally returning additional fields', async () => {\n        const condition = true\n\n        const query = ctx.db\n          .insertInto('person')\n          .output('inserted.first_name')\n          .$if(condition, (qb) => qb.output('inserted.last_name'))\n          .values({\n            first_name: 'Foo',\n            last_name: 'Barson',\n            gender: 'other',\n          })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result.last_name).to.equal('Barson')\n      })\n\n      it('should insert a row and return data using `outputAll`', async () => {\n        const result = await ctx.db\n          .insertInto('person')\n          .outputAll('inserted')\n          .values({\n            gender: 'other',\n            first_name: ctx.db\n              .selectFrom('person')\n              .select(sql<string>`max(first_name)`.as('max_first_name')),\n            last_name: sql`concat(cast(${'Bar'} as varchar), cast(${'son'} as varchar))`,\n          })\n          .executeTakeFirst()\n\n        expect(result).to.containSubset({\n          first_name: 'Sylvester',\n          last_name: 'Barson',\n          gender: 'other',\n        })\n\n        expect(await getNewestPerson(ctx.db)).to.eql({\n          first_name: 'Sylvester',\n          last_name: 'Barson',\n        })\n      })\n    }\n  })\n\n  async function getNewestPerson(\n    db: Kysely<Database>,\n  ): Promise<Pick<Person, 'first_name' | 'last_name'> | undefined> {\n    return await db\n      .selectFrom('person')\n      .select(['first_name', 'last_name'])\n      .where(\n        'id',\n        '=',\n        db.selectFrom('person').select(sql<number>`max(id)`.as('max_id')),\n      )\n      .executeTakeFirst()\n  }\n}\n\nfunction values<R extends Record<string, unknown>, A extends string>(\n  records: R[],\n  alias: A,\n): AliasedRawBuilder<R, A> {\n  const keys = Object.keys(records[0])\n\n  const values = sql.join(\n    records.map((r) => {\n      const v = sql.join(keys.map((k) => sql`${r[k]}`))\n      return sql`(${v})`\n    }),\n  )\n\n  return sql<R>`(values ${values})`.as<A>(\n    sql.raw(`${alias}(${keys.join(', ')})`),\n  )\n}\n"
  },
  {
    "path": "test/node/src/introspect.test.ts",
    "content": "import { sql } from '../../../'\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  expect,\n  insertDefaultDataSet,\n  DIALECTS,\n  createTableWithId,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: introspect`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n\n      if (dialect === 'postgres' || dialect === 'mssql') {\n        await dropSchema()\n        await createSchema()\n      }\n\n      await createView()\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await dropView()\n\n      if (dialect === 'postgres') {\n        await dropSchema()\n      }\n\n      await destroyTest(ctx)\n    })\n\n    describe('getSchemas', () => {\n      it('should get schema names', async () => {\n        const schemas = await ctx.db.introspection.getSchemas()\n\n        if (dialect === 'postgres') {\n          expect(schemas).to.containSubset([\n            { name: 'public' },\n            { name: 'information_schema' },\n            { name: 'pg_catalog' },\n            { name: 'some_schema' },\n            { name: 'dtype_schema' },\n          ])\n        } else if (dialect === 'mysql') {\n          expect(schemas).to.containSubset([\n            { name: 'mysql' },\n            { name: 'information_schema' },\n            { name: 'performance_schema' },\n            { name: 'sys' },\n            { name: 'kysely_test' },\n          ])\n        } else if (dialect === 'mssql') {\n          expect(schemas).to.containSubset([\n            { name: 'dbo' },\n            { name: 'sys' },\n            { name: 'guest' },\n            { name: 'INFORMATION_SCHEMA' },\n            { name: 'some_schema' },\n          ])\n        } else if (dialect === 'sqlite') {\n          expect(schemas).to.eql([])\n        }\n      })\n    })\n\n    describe('getTables', () => {\n      it('should get table metadata', async () => {\n        const meta = await ctx.db.introspection.getTables()\n\n        if (dialect === 'postgres') {\n          expect(meta).to.eql([\n            {\n              name: 'person',\n              isView: false,\n              schema: 'public',\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'int4',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: true,\n                  comment: undefined,\n                },\n                {\n                  name: 'first_name',\n                  dataType: 'varchar',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'middle_name',\n                  dataType: 'varchar',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n\n                {\n                  name: 'last_name',\n                  dataType: 'varchar',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'gender',\n                  dataType: 'varchar',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'marital_status',\n                  dataType: 'varchar',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'children',\n                  dataType: 'int4',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: true,\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'pet',\n              isView: false,\n              schema: 'public',\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'int4',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: true,\n                  comment: undefined,\n                },\n                {\n                  name: 'name',\n                  dataType: 'varchar',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'owner_id',\n                  dataType: 'int4',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'species',\n                  dataType: 'varchar',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'toy',\n              isView: false,\n              schema: 'public',\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'int4',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: true,\n                  comment: undefined,\n                },\n                {\n                  name: 'name',\n                  dataType: 'varchar',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'pet_id',\n                  dataType: 'int4',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'price',\n                  dataType: 'float8',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: 'Price in USD',\n                },\n              ],\n            },\n            {\n              name: 'toy_names',\n              isView: true,\n              schema: 'public',\n              columns: [\n                {\n                  name: 'name',\n                  dataType: 'varchar',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'MixedCaseTable',\n              isView: false,\n              schema: 'some_schema',\n              columns: [\n                {\n                  name: 'some_column',\n                  dataType: 'int4',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: true,\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'pet',\n              isView: false,\n              schema: 'some_schema',\n              columns: [\n                {\n                  name: 'some_column_renamed',\n                  dataType: 'int4',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: false,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: true,\n                  comment: undefined,\n                },\n                {\n                  dataType: 'species',\n                  dataTypeSchema: 'dtype_schema',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: true,\n                  name: 'spcies',\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'pet_partition',\n              isView: false,\n              schema: 'some_schema',\n              columns: [\n                {\n                  name: 'part_column',\n                  dataType: 'text',\n                  dataTypeSchema: 'pg_catalog',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n              ],\n            },\n          ])\n        } else if (dialect === 'mysql') {\n          expect(meta).to.eql([\n            {\n              name: 'person',\n              isView: false,\n              schema: 'kysely_test',\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'int',\n                  isNullable: false,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'first_name',\n                  dataType: 'varchar',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'middle_name',\n                  dataType: 'varchar',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'last_name',\n                  dataType: 'varchar',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n\n                {\n                  name: 'gender',\n                  dataType: 'varchar',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'marital_status',\n                  dataType: 'varchar',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'children',\n                  dataType: 'int',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: true,\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'pet',\n              isView: false,\n              schema: 'kysely_test',\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'int',\n                  isNullable: false,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'name',\n                  dataType: 'varchar',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'owner_id',\n                  dataType: 'int',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'species',\n                  dataType: 'varchar',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'toy',\n              isView: false,\n              schema: 'kysely_test',\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'int',\n                  isNullable: false,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'name',\n                  dataType: 'varchar',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'pet_id',\n                  dataType: 'int',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'price',\n                  dataType: 'double',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: 'Price in USD',\n                },\n              ],\n            },\n            {\n              name: 'toy_names',\n              isView: true,\n              schema: 'kysely_test',\n              columns: [\n                {\n                  dataType: 'varchar',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'name',\n                  comment: undefined,\n                },\n              ],\n            },\n          ])\n        } else if (dialect === 'mssql') {\n          expect(meta).to.eql([\n            {\n              isView: false,\n              name: 'person',\n              schema: 'dbo',\n              columns: [\n                {\n                  dataType: 'int',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: true,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'children',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'varchar',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: true,\n                  name: 'first_name',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'varchar',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'gender',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'int',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: true,\n                  isAutoIncrementing: true,\n                  isNullable: false,\n                  name: 'id',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'varchar',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: true,\n                  name: 'last_name',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'varchar',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: true,\n                  name: 'marital_status',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'varchar',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: true,\n                  name: 'middle_name',\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              isView: false,\n              name: 'pet',\n              schema: 'dbo',\n              columns: [\n                {\n                  dataType: 'int',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: true,\n                  isAutoIncrementing: true,\n                  isNullable: false,\n                  name: 'id',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'varchar',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'name',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'int',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'owner_id',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'varchar',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'species',\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              isView: false,\n              name: 'toy',\n              schema: 'dbo',\n              columns: [\n                {\n                  dataType: 'int',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: true,\n                  isAutoIncrementing: true,\n                  isNullable: false,\n                  name: 'id',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'varchar',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'name',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'int',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'pet_id',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'float',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'price',\n                  comment: 'Price in USD',\n                },\n              ],\n            },\n            {\n              isView: true,\n              name: 'toy_names',\n              schema: 'dbo',\n              columns: [\n                {\n                  dataType: 'varchar',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: false,\n                  name: 'name',\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              isView: false,\n              name: 'pet',\n              schema: 'some_schema',\n              columns: [\n                {\n                  dataType: 'int',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: true,\n                  isAutoIncrementing: true,\n                  isNullable: false,\n                  name: 'some_column',\n                  comment: undefined,\n                },\n                {\n                  dataType: 'int',\n                  dataTypeSchema: 'sys',\n                  hasDefaultValue: true,\n                  isAutoIncrementing: false,\n                  isNullable: true,\n                  name: 'some_column_plus_1',\n                  comment: undefined,\n                },\n              ],\n            },\n          ])\n        } else if (dialect === 'sqlite') {\n          expect(meta).to.eql([\n            {\n              name: 'person',\n              isView: false,\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'INTEGER',\n                  isNullable: true,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'first_name',\n                  dataType: 'varchar(255)',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'middle_name',\n                  dataType: 'varchar(255)',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'last_name',\n                  dataType: 'varchar(255)',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n\n                {\n                  name: 'gender',\n                  dataType: 'varchar(50)',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'marital_status',\n                  dataType: 'varchar(50)',\n                  isNullable: true,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'children',\n                  dataType: 'INTEGER',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: true,\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'pet',\n              isView: false,\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'INTEGER',\n                  isNullable: true,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'name',\n                  dataType: 'varchar(255)',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'owner_id',\n                  dataType: 'INTEGER',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'species',\n                  dataType: 'varchar(50)',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'toy',\n              isView: false,\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'INTEGER',\n                  isNullable: true,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'name',\n                  dataType: 'varchar(255)',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'pet_id',\n                  dataType: 'INTEGER',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n                {\n                  name: 'price',\n                  dataType: 'double precision',\n                  isNullable: false,\n                  isAutoIncrementing: false,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n              ],\n            },\n            {\n              name: 'toy_names',\n              isView: true,\n              columns: [\n                {\n                  dataType: 'varchar(255)',\n                  hasDefaultValue: false,\n                  isAutoIncrementing: false,\n                  isNullable: true,\n                  name: 'name',\n                  comment: undefined,\n                },\n              ],\n            },\n          ])\n        }\n      })\n\n      if (dialect === 'sqlite') {\n        describe('implicit autoincrement', () => {\n          const testTableName = 'implicit_increment_test'\n\n          before(async () => {\n            await createTableWithId(ctx.db.schema, dialect, testTableName, true)\n              .ifNotExists()\n              .execute()\n          })\n\n          after(async () => {\n            await ctx.db.schema.dropTable(testTableName).ifExists().execute()\n          })\n\n          it('should detect autoincrement on implicitly auto incrementing columns', async () => {\n            const tables = await ctx.db.introspection.getTables()\n\n            const testTable = tables.find(\n              (table) => table.name === testTableName,\n            )\n\n            expect(testTable).to.eql({\n              name: testTableName,\n              isView: false,\n              columns: [\n                {\n                  name: 'id',\n                  dataType: 'INTEGER',\n                  isNullable: true,\n                  isAutoIncrementing: true,\n                  hasDefaultValue: false,\n                  comment: undefined,\n                },\n              ],\n            })\n          })\n        })\n      }\n    })\n\n    async function createView() {\n      ctx.db.schema\n        .createView('toy_names')\n        .as(ctx.db.selectFrom('toy').select('name'))\n        .execute()\n    }\n\n    async function dropView() {\n      ctx.db.schema.dropView('toy_names').ifExists().execute()\n    }\n\n    async function createSchema() {\n      await ctx.db.schema.createSchema('some_schema').execute()\n\n      if (dialect === 'postgres') {\n        await ctx.db.schema.createSchema('dtype_schema').execute()\n        await ctx.db.schema\n          .createType('dtype_schema.species')\n          .asEnum(['cat', 'dog', 'frog'])\n          .execute()\n\n        await ctx.db.schema\n          .createTable('some_schema.MixedCaseTable')\n          .addColumn('some_column', 'serial', (col) => col.primaryKey())\n          .execute()\n\n        await ctx.db.schema\n          .createTable('some_schema.pet')\n          .addColumn('some_column', 'serial', (col) => col.primaryKey())\n          .addColumn('spcies', sql`dtype_schema.species`)\n          .execute()\n        // check that a renamed column with sequence is still detected as autoincrement\n        await ctx.db.schema\n          .alterTable('some_schema.pet')\n          .renameColumn('some_column', 'some_column_renamed')\n          .execute()\n        await ctx.db.schema\n          .createTable('some_schema.pet_partition')\n          .addColumn('part_column', 'text')\n          .modifyEnd(sql`PARTITION by LIST (\"part_column\")`)\n          .execute()\n      } else {\n        await ctx.db.schema\n          .createTable('some_schema.pet')\n          .addColumn('some_column', 'integer', (col) =>\n            col.identity().notNull().primaryKey(),\n          )\n          .addColumn('some_column_plus_1', sql``, (col) =>\n            col.modifyEnd(sql`as (some_column + 1)`),\n          )\n          .execute()\n      }\n    }\n\n    async function dropSchema() {\n      await ctx.db.schema.dropTable('some_schema.pet').ifExists().execute()\n      await ctx.db.schema\n        .dropTable('some_schema.MixedCaseTable')\n        .ifExists()\n        .execute()\n      await ctx.db.schema\n        .dropTable('some_schema.pet_partition')\n        .ifExists()\n        .execute()\n      await ctx.db.schema.dropSchema('some_schema').ifExists().execute()\n\n      if (dialect === 'postgres') {\n        await ctx.db.schema\n          .dropType('dtype_schema.species')\n          .ifExists()\n          .execute()\n        await ctx.db.schema.dropSchema('dtype_schema').ifExists().execute()\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/join.test.ts",
    "content": "import { sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  insertPersons,\n  TestContext,\n  testSql,\n  expect,\n  NOT_SUPPORTED,\n  DIALECTS,\n  limit,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: join`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertPersons(ctx, [\n        {\n          first_name: 'Jennifer',\n          last_name: 'Aniston',\n          gender: 'female',\n          pets: [\n            {\n              name: 'Catto',\n              species: 'cat',\n              toys: [{ name: 'spool', price: 10 }],\n            },\n          ],\n        },\n        {\n          first_name: 'Arnold',\n          last_name: 'Schwarzenegger',\n          gender: 'male',\n          pets: [{ name: 'Doggo', species: 'dog' }],\n        },\n        {\n          first_name: 'Sylvester',\n          last_name: 'Stallone',\n          gender: 'male',\n          pets: [{ name: 'Hammo', species: 'hamster' }],\n        },\n      ])\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    describe('inner join', () => {\n      it(`should inner join a table`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .selectAll()\n          .orderBy('person.first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select * from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n          mysql: {\n            sql: `select * from \\`person\\` inner join \\`pet\\` on \\`pet\\`.\\`owner_id\\` = \\`person\\`.\\`id\\` order by \\`person\\`.\\`first_name\\``,\n            parameters: [],\n          },\n          mssql: {\n            sql: `select * from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n          sqlite: {\n            sql: `select * from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(3)\n        expect(result).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            last_name: 'Aniston',\n            name: 'Catto',\n          },\n          {\n            first_name: 'Arnold',\n            last_name: 'Schwarzenegger',\n            name: 'Doggo',\n          },\n          {\n            first_name: 'Sylvester',\n            last_name: 'Stallone',\n            name: 'Hammo',\n          },\n        ])\n      })\n\n      it(`should inner join a subquery`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .innerJoin(\n            ctx.db\n              .selectFrom('pet')\n              .select(['owner_id as oid', 'name'])\n              .as('p'),\n            'p.oid',\n            'person.id',\n          )\n          .selectAll()\n          .orderBy('person.first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              `select * from \"person\"`,\n              `inner join (select \"owner_id\" as \"oid\", \"name\" from \"pet\") as \"p\"`,\n              `on \"p\".\"oid\" = \"person\".\"id\"`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: [],\n          },\n          mysql: {\n            sql: [\n              'select * from `person`',\n              `inner join (select \\`owner_id\\` as \\`oid\\`, \\`name\\` from \\`pet\\`) as \\`p\\``,\n              'on `p`.`oid` = `person`.`id`',\n              'order by `person`.`first_name`',\n            ],\n            parameters: [],\n          },\n          mssql: {\n            sql: [\n              `select * from \"person\"`,\n              `inner join (select \"owner_id\" as \"oid\", \"name\" from \"pet\") as \"p\"`,\n              `on \"p\".\"oid\" = \"person\".\"id\"`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: [],\n          },\n          sqlite: {\n            sql: [\n              `select * from \"person\"`,\n              `inner join (select \"owner_id\" as \"oid\", \"name\" from \"pet\") as \"p\"`,\n              `on \"p\".\"oid\" = \"person\".\"id\"`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: [],\n          },\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(3)\n        expect(result).to.containSubset([\n          {\n            first_name: 'Arnold',\n            last_name: 'Schwarzenegger',\n            name: 'Doggo',\n          },\n          {\n            first_name: 'Jennifer',\n            last_name: 'Aniston',\n            name: 'Catto',\n          },\n          {\n            first_name: 'Sylvester',\n            last_name: 'Stallone',\n            name: 'Hammo',\n          },\n        ])\n      })\n\n      it(`should inner join multiple tables`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .innerJoin('toy', 'toy.pet_id', 'pet.id')\n          .select(['pet.name as pet_name', 'toy.name as toy_name'])\n          .where('first_name', '=', 'Jennifer')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select \"pet\".\"name\" as \"pet_name\", \"toy\".\"name\" as \"toy_name\" from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\" where \"first_name\" = $1`,\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: `select \\`pet\\`.\\`name\\` as \\`pet_name\\`, \\`toy\\`.\\`name\\` as \\`toy_name\\` from \\`person\\` inner join \\`pet\\` on \\`pet\\`.\\`owner_id\\` = \\`person\\`.\\`id\\` inner join \\`toy\\` on \\`toy\\`.\\`pet_id\\` = \\`pet\\`.\\`id\\` where \\`first_name\\` = ?`,\n            parameters: ['Jennifer'],\n          },\n          mssql: {\n            sql: `select \"pet\".\"name\" as \"pet_name\", \"toy\".\"name\" as \"toy_name\" from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\" where \"first_name\" = @1`,\n            parameters: ['Jennifer'],\n          },\n          sqlite: {\n            sql: `select \"pet\".\"name\" as \"pet_name\", \"toy\".\"name\" as \"toy_name\" from \"person\" inner join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\" where \"first_name\" = ?`,\n            parameters: ['Jennifer'],\n          },\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(1)\n        expect(result).to.containSubset([\n          {\n            pet_name: 'Catto',\n            toy_name: 'spool',\n          },\n        ])\n      })\n\n      it('should inner join a table using a complex `on` expression', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .innerJoin('pet', (join) =>\n            join\n              .onRef('pet.owner_id', '=', 'person.id')\n              .on('pet.name', 'in', ['Catto', 'Doggo', 'Hammo'])\n              .on(({ or, eb, ref, selectFrom }) =>\n                or([\n                  eb('pet.species', '=', 'cat'),\n                  eb('species', '=', 'dog'),\n                  eb(\n                    ref('species'),\n                    '=',\n                    selectFrom('pet')\n                      .select(sql<'hamster'>`'hamster'`.as('hamster'))\n                      .$call(limit(1, dialect)),\n                  ),\n                ]),\n              ),\n          )\n          .selectAll()\n          .orderBy('person.first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              `select * from \"person\"`,\n              `inner join \"pet\"`,\n              `on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n              `and \"pet\".\"name\" in ($1, $2, $3)`,\n              `and (\"pet\".\"species\" = $4 or \"species\" = $5 or \"species\" = (select 'hamster' as \"hamster\" from \"pet\" limit $6))`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1],\n          },\n          mysql: {\n            sql: [\n              'select * from `person`',\n              'inner join `pet`',\n              'on `pet`.`owner_id` = `person`.`id`',\n              'and `pet`.`name` in (?, ?, ?)',\n              \"and (`pet`.`species` = ? or `species` = ? or `species` = (select 'hamster' as `hamster` from `pet` limit ?))\",\n              'order by `person`.`first_name`',\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1],\n          },\n          mssql: {\n            sql: [\n              `select * from \"person\"`,\n              `inner join \"pet\"`,\n              `on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n              `and \"pet\".\"name\" in (@1, @2, @3)`,\n              `and (\"pet\".\"species\" = @4 or \"species\" = @5 or \"species\" = (select top(1) 'hamster' as \"hamster\" from \"pet\"))`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog'],\n          },\n          sqlite: {\n            sql: [\n              `select * from \"person\"`,\n              `inner join \"pet\"`,\n              `on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n              `and \"pet\".\"name\" in (?, ?, ?)`,\n              `and (\"pet\".\"species\" = ? or \"species\" = ? or \"species\" = (select 'hamster' as \"hamster\" from \"pet\" limit ?))`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it(`should inner join a table using multiple \"on\" statements`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .innerJoin('pet', (join) =>\n            join\n              .onRef('pet.owner_id', '=', 'person.id')\n              .on('pet.name', 'in', ['Catto', 'Doggo', 'Hammo'])\n              .on((eb) =>\n                eb.or([\n                  eb('pet.species', '=', 'cat'),\n                  eb('species', '=', 'dog'),\n                  eb(\n                    eb.ref('species'),\n                    '=',\n                    eb\n                      .selectFrom('pet')\n                      .select(sql<'hamster'>`'hamster'`.as('hamster'))\n                      .$call(limit(1, dialect)),\n                  ),\n                ]),\n              ),\n          )\n          .selectAll()\n          .orderBy('person.first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              `select * from \"person\"`,\n              `inner join \"pet\"`,\n              `on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n              `and \"pet\".\"name\" in ($1, $2, $3)`,\n              `and (\"pet\".\"species\" = $4 or \"species\" = $5 or \"species\" = (select 'hamster' as \"hamster\" from \"pet\" limit $6))`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1],\n          },\n          mysql: {\n            sql: [\n              'select * from `person`',\n              'inner join `pet`',\n              'on `pet`.`owner_id` = `person`.`id`',\n              'and `pet`.`name` in (?, ?, ?)',\n              \"and (`pet`.`species` = ? or `species` = ? or `species` = (select 'hamster' as `hamster` from `pet` limit ?))\",\n              'order by `person`.`first_name`',\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1],\n          },\n          mssql: {\n            sql: [\n              `select * from \"person\"`,\n              `inner join \"pet\"`,\n              `on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n              `and \"pet\".\"name\" in (@1, @2, @3)`,\n              `and (\"pet\".\"species\" = @4 or \"species\" = @5 or \"species\" = (select top(1) 'hamster' as \"hamster\" from \"pet\"))`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog'],\n          },\n          sqlite: {\n            sql: [\n              `select * from \"person\"`,\n              `inner join \"pet\"`,\n              `on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n              `and \"pet\".\"name\" in (?, ?, ?)`,\n              `and (\"pet\".\"species\" = ? or \"species\" = ? or \"species\" = (select 'hamster' as \"hamster\" from \"pet\" limit ?))`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it(`should inner join a table using \"exists\" statements`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .innerJoin('pet', (join) =>\n            join.on(({ exists, selectFrom }) =>\n              exists(\n                selectFrom('pet as p')\n                  .whereRef('p.id', '=', 'pet.id')\n                  .whereRef('p.owner_id', '=', 'person.id')\n                  .select('id'),\n              ),\n            ),\n          )\n          .select('pet.id')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              `select \"pet\".\"id\" from \"person\"`,\n              `inner join \"pet\" on exists`,\n              `(select \"id\" from \"pet\" as \"p\" where \"p\".\"id\" = \"pet\".\"id\" and \"p\".\"owner_id\" = \"person\".\"id\")`,\n            ],\n            parameters: [],\n          },\n          mysql: {\n            sql: [\n              'select `pet`.`id` from `person`',\n              `inner join \\`pet\\` on exists`,\n              '(select `id` from `pet` as `p` where `p`.`id` = `pet`.`id` and `p`.`owner_id` = `person`.`id`)',\n            ],\n            parameters: [],\n          },\n          mssql: {\n            sql: [\n              `select \"pet\".\"id\" from \"person\"`,\n              `inner join \"pet\" on exists`,\n              `(select \"id\" from \"pet\" as \"p\" where \"p\".\"id\" = \"pet\".\"id\" and \"p\".\"owner_id\" = \"person\".\"id\")`,\n            ],\n            parameters: [],\n          },\n          sqlite: {\n            sql: [\n              `select \"pet\".\"id\" from \"person\"`,\n              `inner join \"pet\" on exists`,\n              `(select \"id\" from \"pet\" as \"p\" where \"p\".\"id\" = \"pet\".\"id\" and \"p\".\"owner_id\" = \"person\".\"id\")`,\n            ],\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n    })\n\n    describe('left join', () => {\n      it(`should left join a table`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .leftJoin('pet', 'pet.owner_id', 'person.id')\n          .selectAll()\n          .orderBy('person.first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select * from \"person\" left join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n          mysql: {\n            sql: `select * from \\`person\\` left join \\`pet\\` on \\`pet\\`.\\`owner_id\\` = \\`person\\`.\\`id\\` order by \\`person\\`.\\`first_name\\``,\n            parameters: [],\n          },\n          mssql: {\n            sql: `select * from \"person\" left join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n          sqlite: {\n            sql: `select * from \"person\" left join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it(`should left join a subquery`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .leftJoin(\n            ctx.db\n              .selectFrom('pet')\n              .select(['owner_id as oid', 'name'])\n              .as('p'),\n            'p.oid',\n            'person.id',\n          )\n          .selectAll()\n          .orderBy('person.first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              `select * from \"person\"`,\n              `left join (select \"owner_id\" as \"oid\", \"name\" from \"pet\") as \"p\"`,\n              `on \"p\".\"oid\" = \"person\".\"id\"`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: [],\n          },\n          mysql: {\n            sql: [\n              'select * from `person`',\n              `left join (select \\`owner_id\\` as \\`oid\\`, \\`name\\` from \\`pet\\`) as \\`p\\``,\n              'on `p`.`oid` = `person`.`id`',\n              'order by `person`.`first_name`',\n            ],\n            parameters: [],\n          },\n          mssql: {\n            sql: [\n              `select * from \"person\"`,\n              `left join (select \"owner_id\" as \"oid\", \"name\" from \"pet\") as \"p\"`,\n              `on \"p\".\"oid\" = \"person\".\"id\"`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: [],\n          },\n          sqlite: {\n            sql: [\n              `select * from \"person\"`,\n              `left join (select \"owner_id\" as \"oid\", \"name\" from \"pet\") as \"p\"`,\n              `on \"p\".\"oid\" = \"person\".\"id\"`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it(`should left join multiple tables`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .leftJoin('pet', 'pet.owner_id', 'person.id')\n          .leftJoin('toy', 'toy.pet_id', 'pet.id')\n          .select(['pet.name as pet_name', 'toy.name as toy_name'])\n          .where('first_name', '=', 'Jennifer')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select \"pet\".\"name\" as \"pet_name\", \"toy\".\"name\" as \"toy_name\" from \"person\" left join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" left join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\" where \"first_name\" = $1`,\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: `select \\`pet\\`.\\`name\\` as \\`pet_name\\`, \\`toy\\`.\\`name\\` as \\`toy_name\\` from \\`person\\` left join \\`pet\\` on \\`pet\\`.\\`owner_id\\` = \\`person\\`.\\`id\\` left join \\`toy\\` on \\`toy\\`.\\`pet_id\\` = \\`pet\\`.\\`id\\` where \\`first_name\\` = ?`,\n            parameters: ['Jennifer'],\n          },\n          mssql: {\n            sql: `select \"pet\".\"name\" as \"pet_name\", \"toy\".\"name\" as \"toy_name\" from \"person\" left join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" left join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\" where \"first_name\" = @1`,\n            parameters: ['Jennifer'],\n          },\n          sqlite: {\n            sql: `select \"pet\".\"name\" as \"pet_name\", \"toy\".\"name\" as \"toy_name\" from \"person\" left join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" left join \"toy\" on \"toy\".\"pet_id\" = \"pet\".\"id\" where \"first_name\" = ?`,\n            parameters: ['Jennifer'],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it(`should left join a table using multiple \"on\" statements`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .leftJoin('pet', (join) =>\n            join\n              .onRef('pet.owner_id', '=', 'person.id')\n              .on('pet.name', 'in', ['Catto', 'Doggo', 'Hammo'])\n              .on(({ or, eb }) =>\n                or([\n                  eb('pet.species', '=', 'cat'),\n                  eb('species', '=', 'dog'),\n                  eb(\n                    sql`${sql.ref('species')}`,\n                    '=',\n                    eb\n                      .selectFrom('pet')\n                      .select(sql`'hamster'`.as('hamster'))\n                      .$call(limit(1, dialect)),\n                  ),\n                ]),\n              ),\n          )\n          .selectAll()\n          .orderBy('person.first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              `select * from \"person\"`,\n              `left join \"pet\"`,\n              `on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n              `and \"pet\".\"name\" in ($1, $2, $3)`,\n              `and (\"pet\".\"species\" = $4 or \"species\" = $5 or \"species\" = (select 'hamster' as \"hamster\" from \"pet\" limit $6))`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1],\n          },\n          mysql: {\n            sql: [\n              'select * from `person`',\n              'left join `pet`',\n              'on `pet`.`owner_id` = `person`.`id`',\n              'and `pet`.`name` in (?, ?, ?)',\n              \"and (`pet`.`species` = ? or `species` = ? or `species` = (select 'hamster' as `hamster` from `pet` limit ?))\",\n              'order by `person`.`first_name`',\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1],\n          },\n          mssql: {\n            sql: [\n              `select * from \"person\"`,\n              `left join \"pet\"`,\n              `on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n              `and \"pet\".\"name\" in (@1, @2, @3)`,\n              `and (\"pet\".\"species\" = @4 or \"species\" = @5 or \"species\" = (select top(1) 'hamster' as \"hamster\" from \"pet\"))`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog'],\n          },\n          sqlite: {\n            sql: [\n              `select * from \"person\"`,\n              `left join \"pet\"`,\n              `on \"pet\".\"owner_id\" = \"person\".\"id\"`,\n              `and \"pet\".\"name\" in (?, ?, ?)`,\n              `and (\"pet\".\"species\" = ? or \"species\" = ? or \"species\" = (select 'hamster' as \"hamster\" from \"pet\" limit ?))`,\n              `order by \"person\".\"first_name\"`,\n            ],\n            parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it(`should left join a table using \"not exists\" statements`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .leftJoin('pet', (join) =>\n            join.on(({ not, exists, selectFrom }) =>\n              not(\n                exists(\n                  selectFrom('pet as p')\n                    .whereRef('p.id', '=', 'pet.id')\n                    .whereRef('p.owner_id', '=', 'person.id')\n                    .select('id'),\n                ),\n              ),\n            ),\n          )\n          .select('pet.id')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select \"pet\".\"id\" from \"person\" left join \"pet\" on not exists (select \"id\" from \"pet\" as \"p\" where \"p\".\"id\" = \"pet\".\"id\" and \"p\".\"owner_id\" = \"person\".\"id\")`,\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select `pet`.`id` from `person` left join `pet` on not exists (select `id` from `pet` as `p` where `p`.`id` = `pet`.`id` and `p`.`owner_id` = `person`.`id`)',\n            parameters: [],\n          },\n          mssql: {\n            sql: `select \"pet\".\"id\" from \"person\" left join \"pet\" on not exists (select \"id\" from \"pet\" as \"p\" where \"p\".\"id\" = \"pet\".\"id\" and \"p\".\"owner_id\" = \"person\".\"id\")`,\n            parameters: [],\n          },\n          sqlite: {\n            sql: `select \"pet\".\"id\" from \"person\" left join \"pet\" on not exists (select \"id\" from \"pet\" as \"p\" where \"p\".\"id\" = \"pet\".\"id\" and \"p\".\"owner_id\" = \"person\".\"id\")`,\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n    })\n\n    describe('right join', () => {\n      it(`should right join a table`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .rightJoin('pet', 'pet.owner_id', 'person.id')\n          .selectAll()\n          .orderBy('person.first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select * from \"person\" right join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n          mysql: {\n            sql: `select * from \\`person\\` right join \\`pet\\` on \\`pet\\`.\\`owner_id\\` = \\`person\\`.\\`id\\` order by \\`person\\`.\\`first_name\\``,\n            parameters: [],\n          },\n          mssql: {\n            sql: `select * from \"person\" right join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n          sqlite: {\n            sql: `select * from \"person\" right join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql' || dialect === 'sqlite') {\n      describe('full join', () => {\n        it(`should full join a table`, async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .fullJoin('pet', 'pet.owner_id', 'person.id')\n            .selectAll()\n            .orderBy('person.first_name')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `select * from \"person\" full join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: `select * from \"person\" full join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n              parameters: [],\n            },\n            sqlite: {\n              sql: `select * from \"person\" full join \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" order by \"person\".\"first_name\"`,\n              parameters: [],\n            },\n          })\n\n          await query.execute()\n        })\n      })\n    }\n\n    describe('cross join', () => {\n      it(`should cross join a table`, async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .crossJoin('pet')\n          .selectAll()\n          .orderBy('person.first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select * from \"person\" cross join \"pet\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select * from `person` cross join `pet` order by `person`.`first_name`',\n            parameters: [],\n          },\n          mssql: {\n            sql: `select * from \"person\" cross join \"pet\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n          sqlite: {\n            sql: `select * from \"person\" cross join \"pet\" order by \"person\".\"first_name\"`,\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql') {\n      describe('lateral join', () => {\n        it('should join an expression laterally', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .innerJoinLateral(\n              (eb) =>\n                eb\n                  .selectFrom('pet')\n                  .select('name')\n                  .whereRef('pet.owner_id', '=', 'person.id')\n                  .as('p'),\n              (join) => join.onTrue(),\n            )\n            .select(['first_name', 'p.name'])\n            .orderBy('first_name')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `select \"first_name\", \"p\".\"name\" from \"person\" inner join lateral (select \"name\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\") as \"p\" on true order by \"first_name\"`,\n              parameters: [],\n            },\n            mysql: {\n              sql: `select \\`first_name\\`, \\`p\\`.\\`name\\` from \\`person\\` inner join lateral (select \\`name\\` from \\`pet\\` where \\`pet\\`.\\`owner_id\\` = \\`person\\`.\\`id\\`) as \\`p\\` on true order by \\`first_name\\``,\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const res = await query.execute()\n          expect(res).to.eql([\n            { first_name: 'Arnold', name: 'Doggo' },\n            { first_name: 'Jennifer', name: 'Catto' },\n            { first_name: 'Sylvester', name: 'Hammo' },\n          ])\n        })\n\n        it('should left join an expression laterally', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .leftJoinLateral(\n              (eb) =>\n                eb\n                  .selectFrom('pet')\n                  .select('name')\n                  .whereRef('pet.owner_id', '=', 'person.id')\n                  .as('p'),\n              (join) => join.onTrue(),\n            )\n            .select(['first_name', 'p.name'])\n            .orderBy('first_name')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `select \"first_name\", \"p\".\"name\" from \"person\" left join lateral (select \"name\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\") as \"p\" on true order by \"first_name\"`,\n              parameters: [],\n            },\n            mysql: {\n              sql: `select \\`first_name\\`, \\`p\\`.\\`name\\` from \\`person\\` left join lateral (select \\`name\\` from \\`pet\\` where \\`pet\\`.\\`owner_id\\` = \\`person\\`.\\`id\\`) as \\`p\\` on true order by \\`first_name\\``,\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const res = await query.execute()\n          expect(res).to.eql([\n            { first_name: 'Arnold', name: 'Doggo' },\n            { first_name: 'Jennifer', name: 'Catto' },\n            { first_name: 'Sylvester', name: 'Hammo' },\n          ])\n        })\n\n        it('should cross join an expression laterally', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .crossJoinLateral((eb) =>\n              eb\n                .selectFrom('pet')\n                .innerJoin('person as owner', 'owner.id', 'pet.owner_id')\n                .select('name')\n                .whereRef('owner.gender', '=', 'person.gender')\n                .as('p'),\n            )\n            .select(['first_name', 'p.name'])\n            .orderBy(['first_name', 'p.name'])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `select \"first_name\", \"p\".\"name\" from \"person\" cross join lateral (select \"name\" from \"pet\" inner join \"person\" as \"owner\" on \"owner\".\"id\" = \"pet\".\"owner_id\" where \"owner\".\"gender\" = \"person\".\"gender\") as \"p\" order by \"first_name\", \"p\".\"name\"`,\n              parameters: [],\n            },\n            mysql: {\n              sql: `select \\`first_name\\`, \\`p\\`.\\`name\\` from \\`person\\` cross join lateral (select \\`name\\` from \\`pet\\` inner join \\`person\\` as \\`owner\\` on \\`owner\\`.\\`id\\` = \\`pet\\`.\\`owner_id\\` where \\`owner\\`.\\`gender\\` = \\`person\\`.\\`gender\\`) as \\`p\\` order by \\`first_name\\`, \\`p\\`.\\`name\\``,\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const res = await query.execute()\n          expect(res).to.eql([\n            { first_name: 'Arnold', name: 'Doggo' },\n            { first_name: 'Arnold', name: 'Hammo' },\n            { first_name: 'Jennifer', name: 'Catto' },\n            { first_name: 'Sylvester', name: 'Doggo' },\n            { first_name: 'Sylvester', name: 'Hammo' },\n          ])\n        })\n      })\n    }\n\n    if (dialect === 'mssql') {\n      describe('apply', () => {\n        it('should cross apply an expression', async () => {\n          const q = ctx.db\n            .selectFrom('person')\n            .crossApply((eb) =>\n              eb\n                .selectFrom('pet')\n                .whereRef('pet.owner_id', '=', 'person.id')\n                .select('pet.name')\n                .as('pets'),\n            )\n            .select(['person.first_name', 'pets.name'])\n            .orderBy('pets.name')\n\n          testSql(q, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n            mssql: {\n              sql: `select \"person\".\"first_name\", \"pets\".\"name\" from \"person\" cross apply (select \"pet\".\"name\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\") as \"pets\" order by \"pets\".\"name\"`,\n              parameters: [],\n            },\n          })\n\n          const result = await q.execute()\n\n          expect(result).to.deep.equal([\n            { first_name: 'Jennifer', name: 'Catto' },\n            { first_name: 'Arnold', name: 'Doggo' },\n            { first_name: 'Sylvester', name: 'Hammo' },\n          ])\n        })\n\n        it('should outer apply an expression', async () => {\n          const q = ctx.db\n            .selectFrom('person')\n            .outerApply((eb) =>\n              eb\n                .selectFrom('pet')\n                .whereRef('pet.owner_id', '=', 'person.id')\n                .select('pet.name')\n                .as('pets'),\n            )\n            .select(['person.first_name', 'pets.name'])\n            .orderBy('pets.name')\n\n          testSql(q, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n            mssql: {\n              sql: `select \"person\".\"first_name\", \"pets\".\"name\" from \"person\" outer apply (select \"pet\".\"name\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\") as \"pets\" order by \"pets\".\"name\"`,\n              parameters: [],\n            },\n          })\n\n          const result = await q.execute()\n\n          expect(result).to.deep.equal([\n            { first_name: 'Jennifer', name: 'Catto' },\n            { first_name: 'Arnold', name: 'Doggo' },\n            { first_name: 'Sylvester', name: 'Hammo' },\n          ])\n        })\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/json-traversal.test.ts",
    "content": "import {\n  ColumnDefinitionBuilder,\n  JSONColumnType,\n  ParseJSONResultsPlugin,\n  SqlBool,\n  sql,\n} from '../../..'\nimport {\n  BuiltInDialect,\n  DIALECTS,\n  NOT_SUPPORTED,\n  clearDatabase,\n  destroyTest,\n  expect,\n  initTest,\n  insertDefaultDataSet,\n  testSql,\n} from './test-setup.js'\n\ntype TestContext = Awaited<ReturnType<typeof initJSONTest>>\n\nfor (const dialect of DIALECTS.filter((dialect) => dialect !== 'mssql')) {\n  describe(`${dialect}: json traversal`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initJSONTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultJSONDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearJSONDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyJSONTest(ctx)\n    })\n\n    if (dialect === 'mysql' || dialect === 'sqlite') {\n      describe('JSON reference using JSON Path syntax ($)', () => {\n        const jsonOperator = dialect === 'mysql' ? '->$' : '->>$'\n\n        it(`should execute a query with column${jsonOperator}.key in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb.ref('website', jsonOperator).key('url').as('website_url'),\n            )\n\n          testSql(query, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              parameters: [],\n              sql: \"select `website`->'$.url' as `website_url` from `person_metadata`\",\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"website\"->>'$.url' as \"website_url\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { website_url: 'https://www.jenniferaniston.com' },\n            { website_url: 'https://www.arnoldschwarzenegger.com' },\n            { website_url: 'https://www.sylvesterstallone.com' },\n          ])\n        })\n\n        it(`should execute a query with column${jsonOperator}[0] in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb.ref('nicknames', jsonOperator).at(0).as('nickname'),\n            )\n\n          testSql(query, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              parameters: [],\n              sql: \"select `nicknames`->'$[0]' as `nickname` from `person_metadata`\",\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"nicknames\"->>'$[0]' as \"nickname\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { nickname: 'J.A.' },\n            { nickname: 'A.S.' },\n            { nickname: 'S.S.' },\n          ])\n        })\n\n        it(`should execute a query with column${jsonOperator}.key.key in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb\n                .ref('profile', jsonOperator)\n                .key('auth')\n                .key('roles')\n                .as('roles'),\n            )\n\n          testSql(query, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              parameters: [],\n              sql: \"select `profile`->'$.auth.roles' as `roles` from `person_metadata`\",\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"profile\"->>'$.auth.roles' as \"roles\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { roles: ['contributor', 'moderator'] },\n            { roles: ['contributor', 'moderator'] },\n            { roles: ['contributor', 'moderator'] },\n          ])\n        })\n\n        it(`should execute a query with column${jsonOperator}.key[0] in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb.ref('profile', jsonOperator).key('tags').at(0).as('main_tag'),\n            )\n\n          testSql(query, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              parameters: [],\n              sql: \"select `profile`->'$.tags[0]' as `main_tag` from `person_metadata`\",\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"profile\"->>'$.tags[0]' as \"main_tag\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { main_tag: 'awesome' },\n            { main_tag: 'awesome' },\n            { main_tag: 'awesome' },\n          ])\n        })\n\n        it(`should execute a query with column${jsonOperator}[0].key in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb\n                .ref('experience', jsonOperator)\n                .at(0)\n                .key('establishment')\n                .as('establishment'),\n            )\n\n          testSql(query, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              parameters: [],\n              sql: \"select `experience`->'$[0].establishment' as `establishment` from `person_metadata`\",\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"experience\"->>'$[0].establishment' as \"establishment\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { establishment: 'The University of Life' },\n            { establishment: 'The University of Life' },\n            { establishment: 'The University of Life' },\n          ])\n        })\n\n        it(`should execute a query with column${jsonOperator}[0][0] in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb\n                .ref('schedule', jsonOperator)\n                .at(0)\n                .at(0)\n                .as('january_1st_schedule'),\n            )\n\n          testSql(query, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              parameters: [],\n              sql: \"select `schedule`->'$[0][0]' as `january_1st_schedule` from `person_metadata`\",\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"schedule\"->>'$[0][0]' as \"january_1st_schedule\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] },\n            { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] },\n            { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] },\n          ])\n        })\n\n        if (dialect === 'mysql') {\n          it('should execute a query with column->$[last] in select clause', async () => {\n            const query = ctx.db\n              .selectFrom('person_metadata')\n              .select((eb) =>\n                eb.ref('nicknames', '->$').at('last').as('nickname'),\n              )\n\n            testSql(query, dialect, {\n              postgres: NOT_SUPPORTED,\n              mysql: {\n                parameters: [],\n                sql: \"select `nicknames`->'$[last]' as `nickname` from `person_metadata`\",\n              },\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            const results = await query.execute()\n\n            expect(results).to.containSubset([\n              { nickname: 'Aniston the Magnificent' },\n              { nickname: 'Schwarzenegger the Magnificent' },\n              { nickname: 'Stallone the Magnificent' },\n            ])\n          })\n        }\n\n        if (dialect === 'sqlite') {\n          it('should execute a query with column->>$[#-1] in select clause', async () => {\n            const query = ctx.db\n              .selectFrom('person_metadata')\n              .select((eb) =>\n                eb.ref('nicknames', '->>$').at('#-1').as('nickname'),\n              )\n\n            testSql(query, dialect, {\n              postgres: NOT_SUPPORTED,\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: {\n                parameters: [],\n                sql: `select \"nicknames\"->>'$[#-1]' as \"nickname\" from \"person_metadata\"`,\n              },\n            })\n\n            const results = await query.execute()\n\n            expect(results).to.containSubset([\n              { nickname: 'Aniston the Magnificent' },\n              { nickname: 'Schwarzenegger the Magnificent' },\n              { nickname: 'Stallone the Magnificent' },\n            ])\n          })\n        }\n\n        const expectedBooleanValue = dialect === 'mysql' ? true : 1\n\n        it(`should execute a query with column${jsonOperator} in select clause with non-string properties`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) => [\n              eb\n                .ref('profile', jsonOperator)\n                .key('auth')\n                .key('is_verified')\n                .as('is_verified'),\n              eb\n                .ref('profile', jsonOperator)\n                .key('auth')\n                .key('login_count')\n                .as('login_count'),\n              eb.ref('profile', jsonOperator).key('avatar').as('avatar'),\n            ])\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            {\n              is_verified: expectedBooleanValue,\n              login_count: 12,\n              avatar: null,\n            },\n          ])\n        })\n\n        it(`should execute a query with column${jsonOperator}.key.key in where clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .where((eb) =>\n              eb(\n                eb.ref('profile', jsonOperator).key('auth').key('login_count'),\n                '=',\n                12,\n              ),\n            )\n            .selectAll()\n\n          testSql(query, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              parameters: [12],\n              sql: \"select * from `person_metadata` where `profile`->'$.auth.login_count' = ?\",\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [12],\n              sql: `select * from \"person_metadata\" where \"profile\"->>'$.auth.login_count' = ?`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.have.length(1)\n          expect(results[0].profile.auth.login_count).to.equal(12)\n        })\n\n        it(`should execute a query with column${jsonOperator}.key.key in order by clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .orderBy(\n              (eb) =>\n                eb.ref('profile', jsonOperator).key('auth').key('login_count'),\n              'desc',\n            )\n            .selectAll()\n\n          testSql(query, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              parameters: [],\n              sql: \"select * from `person_metadata` order by `profile`->'$.auth.login_count' desc\",\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select * from \"person_metadata\" order by \"profile\"->>'$.auth.login_count' desc`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.have.length(3)\n          expect(results[0].profile.auth.login_count).to.equal(14)\n          expect(results[1].profile.auth.login_count).to.equal(13)\n          expect(results[2].profile.auth.login_count).to.equal(12)\n        })\n      })\n\n      describe('Standalone JSON path syntax ($)', () => {\n        it('should execute a query with json_set function', async () => {\n          const lastItem = dialect === 'mysql' ? 'last' : '#-1'\n\n          const query = ctx.db\n            .updateTable('person_metadata')\n            .set('experience', (eb) =>\n              eb.fn('json_set', [\n                'experience',\n                eb.jsonPath<'experience'>().at(lastItem).key('establishment'),\n                eb.val('Papa Johns'),\n              ]),\n            )\n            .where('person_id', '=', 911)\n\n          testSql(query, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              parameters: ['Papa Johns', 911],\n              sql: \"update `person_metadata` set `experience` = json_set(`experience`, '$[last].establishment', ?) where `person_id` = ?\",\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: ['Papa Johns', 911],\n              sql: `update \"person_metadata\" set \"experience\" = json_set(\"experience\", '$[#-1].establishment', ?) where \"person_id\" = ?`,\n            },\n          })\n\n          await query.execute()\n        })\n      })\n    }\n\n    if (dialect === 'postgres' || dialect === 'sqlite') {\n      describe('JSON reference using PostgreSQL-style syntax (->->->>)', () => {\n        const jsonOperator = dialect === 'postgres' ? '->' : '->>'\n\n        it(`should execute a query with column${jsonOperator}key in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb.ref('website', jsonOperator).key('url').as('website_url'),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              parameters: [],\n              sql: `select \"website\"->'url' as \"website_url\" from \"person_metadata\"`,\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"website\"->>'url' as \"website_url\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { website_url: 'https://www.jenniferaniston.com' },\n            { website_url: 'https://www.arnoldschwarzenegger.com' },\n            { website_url: 'https://www.sylvesterstallone.com' },\n          ])\n        })\n\n        it(`should execute a query with column${jsonOperator}0 in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb.ref('nicknames', jsonOperator).at(0).as('nickname'),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              parameters: [],\n              sql: `select \"nicknames\"->0 as \"nickname\" from \"person_metadata\"`,\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"nicknames\"->>0 as \"nickname\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { nickname: 'J.A.' },\n            { nickname: 'A.S.' },\n            { nickname: 'S.S.' },\n          ])\n        })\n\n        it(`should execute a query with column->key${jsonOperator}key in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb\n                .ref('profile', jsonOperator)\n                .key('auth')\n                .key('roles')\n                .as('roles'),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              parameters: [],\n              sql: `select \"profile\"->'auth'->'roles' as \"roles\" from \"person_metadata\"`,\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"profile\"->'auth'->>'roles' as \"roles\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { roles: ['contributor', 'moderator'] },\n            { roles: ['contributor', 'moderator'] },\n            { roles: ['contributor', 'moderator'] },\n          ])\n        })\n\n        it(`should execute a query with column->key${jsonOperator}0 in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb.ref('profile', jsonOperator).key('tags').at(0).as('main_tag'),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              parameters: [],\n              sql: `select \"profile\"->'tags'->0 as \"main_tag\" from \"person_metadata\"`,\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"profile\"->'tags'->>0 as \"main_tag\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { main_tag: 'awesome' },\n            { main_tag: 'awesome' },\n            { main_tag: 'awesome' },\n          ])\n        })\n\n        it(`should execute a query with column->0${jsonOperator}key in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb\n                .ref('experience', jsonOperator)\n                .at(0)\n                .key('establishment')\n                .as('establishment'),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              parameters: [],\n              sql: `select \"experience\"->0->'establishment' as \"establishment\" from \"person_metadata\"`,\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"experience\"->0->>'establishment' as \"establishment\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { establishment: 'The University of Life' },\n            { establishment: 'The University of Life' },\n            { establishment: 'The University of Life' },\n          ])\n        })\n\n        it(`should execute a query with column->0${jsonOperator}0 in select clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) =>\n              eb\n                .ref('schedule', jsonOperator)\n                .at(0)\n                .at(0)\n                .as('january_1st_schedule'),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              parameters: [],\n              sql: `select \"schedule\"->0->0 as \"january_1st_schedule\" from \"person_metadata\"`,\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select \"schedule\"->0->>0 as \"january_1st_schedule\" from \"person_metadata\"`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] },\n            { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] },\n            { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] },\n          ])\n        })\n\n        if (dialect === 'postgres') {\n          it('should execute a query with column->-1 in select clause', async () => {\n            const query = ctx.db\n              .selectFrom('person_metadata')\n              .select((eb) => eb.ref('nicknames', '->').at(-1).as('nickname'))\n\n            testSql(query, dialect, {\n              postgres: {\n                parameters: [],\n                sql: `select \"nicknames\"->-1 as \"nickname\" from \"person_metadata\"`,\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            const results = await query.execute()\n\n            expect(results).to.containSubset([\n              { nickname: 'Aniston the Magnificent' },\n              { nickname: 'Schwarzenegger the Magnificent' },\n              { nickname: 'Stallone the Magnificent' },\n            ])\n          })\n        }\n\n        const expectedBooleanValue = dialect === 'postgres' ? true : 1\n\n        it(`should execute a query with column${jsonOperator} in select clause with non-string properties`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .select((eb) => [\n              eb\n                .ref('profile', jsonOperator)\n                .key('auth')\n                .key('is_verified')\n                .as('is_verified'),\n              eb\n                .ref('profile', jsonOperator)\n                .key('auth')\n                .key('login_count')\n                .as('login_count'),\n              eb.ref('profile', jsonOperator).key('avatar').as('avatar'),\n            ])\n\n          const results = await query.execute()\n\n          expect(results).to.containSubset([\n            {\n              is_verified: expectedBooleanValue,\n              login_count: 12,\n              avatar: null,\n            },\n          ])\n        })\n\n        it(`should execute a query with column->key${jsonOperator}key in where clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .where((eb) =>\n              eb(\n                eb.ref('profile', jsonOperator).key('auth').key('login_count'),\n                '=',\n                12,\n              ),\n            )\n            .selectAll()\n\n          testSql(query, dialect, {\n            postgres: {\n              parameters: [12],\n              sql: `select * from \"person_metadata\" where \"profile\"->'auth'->'login_count' = $1`,\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [12],\n              sql: `select * from \"person_metadata\" where \"profile\"->'auth'->>'login_count' = ?`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.have.length(1)\n          expect(results[0].profile.auth.login_count).to.equal(12)\n        })\n\n        it(`should execute a query with column->key${jsonOperator}key in order by clause`, async () => {\n          const query = ctx.db\n            .selectFrom('person_metadata')\n            .orderBy(\n              (eb) =>\n                eb.ref('profile', jsonOperator).key('auth').key('login_count'),\n              'desc',\n            )\n            .selectAll()\n\n          testSql(query, dialect, {\n            postgres: {\n              parameters: [],\n              sql: `select * from \"person_metadata\" order by \"profile\"->'auth'->'login_count' desc`,\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              parameters: [],\n              sql: `select * from \"person_metadata\" order by \"profile\"->'auth'->>'login_count' desc`,\n            },\n          })\n\n          const results = await query.execute()\n\n          expect(results).to.have.length(3)\n          expect(results[0].profile.auth.login_count).to.equal(14)\n          expect(results[1].profile.auth.login_count).to.equal(13)\n          expect(results[2].profile.auth.login_count).to.equal(12)\n        })\n      })\n    }\n  })\n}\n\nasync function initJSONTest<D extends BuiltInDialect>(\n  ctx: Mocha.Context,\n  dialect: D,\n) {\n  const testContext = await initTest(ctx, dialect)\n\n  let db = testContext.db.withTables<{\n    person_metadata: {\n      person_id: number\n      website: JSONColumnType<{ url: string }>\n      nicknames: JSONColumnType<string[]>\n      profile: JSONColumnType<{\n        auth: {\n          roles: string[]\n          last_login?: { device: string }\n          is_verified: SqlBool\n          login_count: number\n        }\n        avatar: string | null\n        tags: string[]\n      }>\n      experience: JSONColumnType<\n        {\n          establishment: string\n        }[]\n      >\n      schedule: JSONColumnType<{ name: string; time: string }[][][]>\n    }\n  }>()\n\n  if (dialect === 'sqlite') {\n    db = db.withPlugin(new ParseJSONResultsPlugin())\n  }\n\n  const jsonColumnDataType = resolveJSONColumnDataType(dialect)\n  const notNull = (cb: ColumnDefinitionBuilder) => cb.notNull()\n\n  await db.schema\n    .createTable('person_metadata')\n    .addColumn('person_id', 'integer', (cb) =>\n      cb.primaryKey().references('person.id'),\n    )\n    .addColumn('website', jsonColumnDataType, notNull)\n    .addColumn('nicknames', jsonColumnDataType, notNull)\n    .addColumn('profile', jsonColumnDataType, notNull)\n    .addColumn('experience', jsonColumnDataType, notNull)\n    .addColumn('schedule', jsonColumnDataType, notNull)\n    .execute()\n\n  return { ...testContext, db }\n}\n\nfunction resolveJSONColumnDataType(dialect: BuiltInDialect) {\n  switch (dialect) {\n    case 'postgres':\n      return 'jsonb'\n    case 'mysql':\n      return 'json'\n    case 'mssql':\n      return sql`nvarchar(max)`\n    case 'sqlite':\n      return 'text'\n  }\n}\n\nasync function insertDefaultJSONDataSet(ctx: TestContext) {\n  await insertDefaultDataSet(ctx as any)\n\n  const people = await ctx.db\n    .selectFrom('person')\n    .select(['id', 'first_name', 'last_name'])\n    .execute()\n\n  await ctx.db\n    .insertInto('person_metadata')\n    .values(\n      people\n        .filter((person) => person.first_name && person.last_name)\n        .map((person, index) => ({\n          person_id: person.id,\n          website: JSON.stringify({\n            url: `https://www.${person.first_name!.toLowerCase()}${person.last_name!.toLowerCase()}.com`,\n          }),\n          nicknames: JSON.stringify([\n            `${person.first_name![0]}.${person.last_name![0]}.`,\n            `${person.first_name} the Great`,\n            `${person.last_name} the Magnificent`,\n          ]),\n          profile: JSON.stringify({\n            tags: ['awesome'],\n            auth: {\n              roles: ['contributor', 'moderator'],\n              last_login: {\n                device: 'android',\n              },\n              login_count: 12 + index,\n              is_verified: true,\n            },\n            avatar: null,\n          }),\n          experience: JSON.stringify([\n            {\n              establishment: 'The University of Life',\n            },\n          ]),\n          schedule: JSON.stringify([[[{ name: 'Gym', time: '12:15' }]]]),\n        })),\n    )\n    .execute()\n}\n\nasync function clearJSONDatabase(ctx: TestContext) {\n  await ctx.db.deleteFrom('person_metadata').execute()\n  await clearDatabase(ctx as any)\n}\n\nasync function destroyJSONTest(ctx: TestContext) {\n  await ctx.db.schema.dropTable('person_metadata').execute()\n  await destroyTest(ctx as any)\n}\n"
  },
  {
    "path": "test/node/src/json.test.ts",
    "content": "import {\n  Generated,\n  Kysely,\n  RawBuilder,\n  sql,\n  ParseJSONResultsPlugin,\n  NumericString,\n  expressionBuilder,\n} from '../../..'\nimport {\n  jsonArrayFrom as pg_jsonArrayFrom,\n  jsonObjectFrom as pg_jsonObjectFrom,\n  jsonBuildObject as pg_jsonBuildObject,\n} from '../../../helpers/postgres'\nimport {\n  jsonArrayFrom as mysql_jsonArrayFrom,\n  jsonObjectFrom as mysql_jsonObjectFrom,\n  jsonBuildObject as mysql_jsonBuildObject,\n} from '../../../helpers/mysql'\nimport {\n  jsonArrayFrom as mssql_jsonArrayFrom,\n  jsonObjectFrom as mssql_jsonObjectFrom,\n  jsonBuildObject as mssql_jsonBuildObject,\n} from '../../../helpers/mssql'\nimport {\n  jsonArrayFrom as sqlite_jsonArrayFrom,\n  jsonObjectFrom as sqlite_jsonObjectFrom,\n  jsonBuildObject as sqlite_jsonBuildObject,\n} from '../../../helpers/sqlite'\n\nimport {\n  destroyTest,\n  initTest,\n  TestContext,\n  expect,\n  Database,\n  insertDefaultDataSet,\n  clearDatabase,\n  DIALECTS,\n  orderBy,\n  limit,\n} from './test-setup.js'\n\ninterface JsonTable {\n  id: Generated<number>\n  data: {\n    number_field: number\n    nested: {\n      string_field: string\n    }\n  }\n}\n\nconst jsonFunctions = {\n  postgres: {\n    jsonArrayFrom: pg_jsonArrayFrom,\n    jsonObjectFrom: pg_jsonObjectFrom,\n    jsonBuildObject: pg_jsonBuildObject,\n  },\n  mysql: {\n    jsonArrayFrom: mysql_jsonArrayFrom,\n    jsonObjectFrom: mysql_jsonObjectFrom,\n    jsonBuildObject: mysql_jsonBuildObject,\n  },\n  mssql: {\n    jsonArrayFrom: mssql_jsonArrayFrom,\n    jsonObjectFrom: mssql_jsonObjectFrom,\n    jsonBuildObject: mssql_jsonBuildObject,\n  },\n  sqlite: {\n    jsonArrayFrom: sqlite_jsonArrayFrom,\n    jsonObjectFrom: sqlite_jsonObjectFrom,\n    jsonBuildObject: sqlite_jsonBuildObject,\n  },\n} as const\n\nfor (const dialect of DIALECTS) {\n  const { jsonArrayFrom, jsonObjectFrom, jsonBuildObject } =\n    jsonFunctions[dialect]\n\n  describe(`${dialect} json tests`, () => {\n    let ctx: TestContext\n    let db: Kysely<Database & { json_table: JsonTable }>\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n\n      if (dialect === 'postgres') {\n        await ctx.db.schema\n          .createTable('json_table')\n          .ifNotExists()\n          .addColumn('id', 'serial', (col) => col.primaryKey())\n          .addColumn('data', 'jsonb')\n          .execute()\n      } else if (dialect === 'mssql') {\n        await sql`if object_id(N'json_table', N'U') is null begin create table json_table (id int primary key identity, data nvarchar(1024)); end;`.execute(\n          ctx.db,\n        )\n      } else {\n        await ctx.db.schema\n          .createTable('json_table')\n          .ifNotExists()\n          .addColumn('id', 'integer', (col) => col.autoIncrement().primaryKey())\n          .addColumn('data', 'json')\n          .execute()\n      }\n\n      db = ctx.db.withTables<{ json_table: JsonTable }>()\n\n      if (dialect === 'mssql' || dialect === 'sqlite') {\n        db = db.withPlugin(new ParseJSONResultsPlugin())\n      }\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n\n      // Insert a couple of toys for Doggo.\n      for (const name of ['Teddy', 'Rope']) {\n        await ctx.db\n          .insertInto('toy')\n          .values((eb) => ({\n            name,\n            price: 10,\n            pet_id: eb\n              .selectFrom('pet')\n              .select('id')\n              .where('name', '=', 'Doggo'),\n          }))\n          .execute()\n      }\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    afterEach(async () => {\n      await db.deleteFrom('json_table').execute()\n    })\n\n    after(async () => {\n      await ctx.db.schema.dropTable('json_table').ifExists().execute()\n      await destroyTest(ctx)\n    })\n\n    it('should insert a row with a json value', async () => {\n      const result = await db\n        .insertInto('json_table')\n        .values({\n          data: toJson({\n            number_field: 1,\n            nested: {\n              string_field: 'a',\n            },\n          }),\n        })\n        .executeTakeFirstOrThrow()\n\n      expect(result.numInsertedOrUpdatedRows).to.equal(1n)\n    })\n\n    if (dialect === 'postgres') {\n      it('should update json data of a row using the subscript syntax and a raw sql snippet', async () => {\n        await db\n          .insertInto('json_table')\n          .values({\n            data: toJson({\n              number_field: 1,\n              nested: { string_field: 'a' },\n            }),\n          })\n          .executeTakeFirstOrThrow()\n\n        const newValue = Math.random()\n        await db\n          .updateTable('json_table')\n          .set(sql`data['number_field']`, newValue)\n          .executeTakeFirstOrThrow()\n\n        const result = await db\n          .selectFrom('json_table')\n          .select('data')\n          .executeTakeFirstOrThrow()\n\n        expect(result.data.number_field).to.equal(newValue)\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should aggregate a joined table using json_agg', async () => {\n        const res = await db\n          .selectFrom('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .select((eb) => ['first_name', eb.fn.jsonAgg('pet').as('pets')])\n          .groupBy('person.first_name')\n          .execute()\n\n        expect(res).to.have.length(3)\n        expect(res).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            pets: [{ name: 'Catto', species: 'cat' }],\n          },\n          {\n            first_name: 'Arnold',\n            pets: [\n              {\n                name: 'Doggo',\n                species: 'dog',\n              },\n            ],\n          },\n          {\n            first_name: 'Sylvester',\n            pets: [{ name: 'Hammo', species: 'hamster' }],\n          },\n        ])\n      })\n\n      it('should aggregate a joined table using json_agg and distinct', async () => {\n        const res = await db\n          .selectFrom('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .select((eb) => [\n            'first_name',\n            eb.fn.jsonAgg('pet').distinct().as('pets'),\n          ])\n          .groupBy('person.first_name')\n          .execute()\n\n        expect(res).to.have.length(3)\n        expect(res).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            pets: [{ name: 'Catto', species: 'cat' }],\n          },\n          {\n            first_name: 'Arnold',\n            pets: [\n              {\n                name: 'Doggo',\n                species: 'dog',\n              },\n            ],\n          },\n          {\n            first_name: 'Sylvester',\n            pets: [{ name: 'Hammo', species: 'hamster' }],\n          },\n        ])\n      })\n\n      it('should aggregate a subquery using json_agg', async () => {\n        const res = await db\n          .selectFrom('person')\n          .select((eb) => [\n            'first_name',\n            eb\n              .selectFrom('pet')\n              .select((eb) => eb.fn.jsonAgg('pet').as('pet'))\n              .whereRef('pet.owner_id', '=', 'person.id')\n              .as('pets'),\n          ])\n          .execute()\n\n        expect(res).to.have.length(3)\n        expect(res).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            pets: [{ name: 'Catto', species: 'cat' }],\n          },\n          {\n            first_name: 'Arnold',\n            pets: [\n              {\n                name: 'Doggo',\n                species: 'dog',\n              },\n            ],\n          },\n          {\n            first_name: 'Sylvester',\n            pets: [{ name: 'Hammo', species: 'hamster' }],\n          },\n        ])\n      })\n\n      it('should aggregate a subquery using json_agg and eb.table', async () => {\n        const res = await db\n          .selectFrom('person')\n          .select((eb) => [\n            'first_name',\n            eb\n              .selectFrom('pet')\n              .select((eb) => eb.fn.jsonAgg(eb.table('pet')).as('pet'))\n              .whereRef('pet.owner_id', '=', 'person.id')\n              .as('pets'),\n          ])\n          .execute()\n\n        expect(res).to.have.length(3)\n        expect(res).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            pets: [{ name: 'Catto', species: 'cat' }],\n          },\n          {\n            first_name: 'Arnold',\n            pets: [\n              {\n                name: 'Doggo',\n                species: 'dog',\n              },\n            ],\n          },\n          {\n            first_name: 'Sylvester',\n            pets: [{ name: 'Hammo', species: 'hamster' }],\n          },\n        ])\n      })\n\n      it('should aggregate a column using json_agg', async () => {\n        const res = await db\n          .selectFrom('pet')\n          .leftJoin('person', 'person.id', 'pet.owner_id')\n          .select((eb) => [\n            eb.fn.jsonAgg('pet.name').as('petName'),\n            'person.first_name',\n          ])\n          .groupBy('person.first_name')\n          .execute()\n\n        expect(res).to.have.length(3)\n        expect(res).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            petName: ['Catto'],\n          },\n          {\n            first_name: 'Arnold',\n            petName: ['Doggo'],\n          },\n          {\n            first_name: 'Sylvester',\n            petName: ['Hammo'],\n          },\n        ])\n      })\n\n      it('should jsonify a joined table using to_json', async () => {\n        const res = await db\n          .selectFrom('person')\n          .innerJoin('pet', 'pet.owner_id', 'person.id')\n          .select((eb) => ['first_name', eb.fn.toJson('pet').as('pet')])\n          .execute()\n\n        expect(res).to.have.length(3)\n        expect(res).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            pet: { name: 'Catto', species: 'cat' },\n          },\n          {\n            first_name: 'Arnold',\n            pet: {\n              name: 'Doggo',\n              species: 'dog',\n            },\n          },\n          {\n            first_name: 'Sylvester',\n            pet: { name: 'Hammo', species: 'hamster' },\n          },\n        ])\n      })\n    }\n\n    it('should select subqueries as nested json objects', async () => {\n      const query = db.selectFrom('person').select((eb) => [\n        'person.first_name',\n\n        // Nest all pets for each person\n        jsonArrayFrom(\n          eb\n            .selectFrom('pet')\n            .select((eb) => [\n              'name',\n              'species',\n\n              // Nest all toys for each pet\n              jsonArrayFrom(\n                eb\n                  .selectFrom('toy')\n                  .select('toy.name')\n                  .whereRef('toy.pet_id', '=', 'pet.id')\n                  .$call(orderBy('toy.name', 'asc', dialect)),\n              ).as('toys'),\n            ])\n            .whereRef('owner_id', '=', 'person.id')\n            .$call(orderBy('pet.name', 'asc', dialect)),\n        ).as('pets'),\n\n        // Nest the first found dog the person owns\n        jsonObjectFrom(\n          eb\n            .selectFrom('pet')\n            .select('name as doggo_name')\n            .whereRef('owner_id', '=', 'person.id')\n            .where('species', '=', 'dog')\n            .orderBy('name', 'asc')\n            .$call(limit(1, dialect)),\n        ).as('doggo'),\n\n        // Nest an object that holds the person's formatted name\n        jsonBuildObject({\n          first: eb.ref('first_name'),\n          last: eb.ref('last_name'),\n          full:\n            dialect === 'sqlite'\n              ? sql<string>`first_name || ' ' || last_name`\n              : eb.fn('concat', ['first_name', sql.lit(' '), 'last_name']),\n        }).as('name'),\n\n        // Nest an empty list\n        jsonArrayFrom(\n          eb\n            .selectFrom('pet')\n            .select('id')\n            .where(sql<boolean>`1 = 2`),\n        ).as('emptyList'),\n      ])\n\n      const res = await query.execute()\n\n      if (dialect === 'mysql') {\n        // MySQL json_arrayagg produces an array with undefined order\n        // https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-arrayagg\n        res[1].pets[0].toys.sort((a, b) => a.name.localeCompare(b.name))\n      }\n\n      expect(res).to.eql([\n        {\n          first_name: 'Jennifer',\n          pets: [{ name: 'Catto', species: 'cat', toys: [] }],\n          emptyList: [],\n          doggo: null,\n          name: {\n            last: 'Aniston',\n            first: 'Jennifer',\n            full: 'Jennifer Aniston',\n          },\n        },\n        {\n          first_name: 'Arnold',\n          pets: [\n            {\n              name: 'Doggo',\n              species: 'dog',\n              toys: [{ name: 'Rope' }, { name: 'Teddy' }],\n            },\n          ],\n          emptyList: [],\n          doggo: { doggo_name: 'Doggo' },\n          name: {\n            last: 'Schwarzenegger',\n            first: 'Arnold',\n            full: 'Arnold Schwarzenegger',\n          },\n        },\n        {\n          first_name: 'Sylvester',\n          pets: [{ name: 'Hammo', species: 'hamster', toys: [] }],\n          emptyList: [],\n          doggo: null,\n          name: {\n            last: 'Stallone',\n            first: 'Sylvester',\n            full: 'Sylvester Stallone',\n          },\n        },\n      ])\n    })\n\n    it('should dehydrate numeric strings to numbers', async () => {\n      const bigNumber = sql<NumericString | number>`9007199254740991`.as(\n        'bigNumber',\n      )\n      const number = sql<NumericString | number>`42`.as('number')\n\n      const result = await db\n        .selectNoFrom([\n          bigNumber,\n          number,\n          jsonObjectFrom(db.selectNoFrom([bigNumber, number]))\n            .$notNull()\n            .as('dehydrated'),\n        ])\n        .executeTakeFirstOrThrow()\n\n      expect(typeof result.bigNumber).to.equal(\n        {\n          postgres: 'string',\n          mysql: 'string',\n          mssql: 'number',\n          sqlite: 'number',\n        }[dialect],\n      )\n      expect(typeof result.number).to.equal(\n        {\n          postgres: 'number',\n          mysql: 'string',\n          mssql: 'number',\n          sqlite: 'number',\n        }[dialect],\n      )\n      expect(typeof result.dehydrated.bigNumber).to.equal('number')\n      expect(typeof result.dehydrated.number).to.equal('number')\n\n      const expectedType0: NumericString | number = result.bigNumber\n      const expectedType1: NumericString | number = result.number\n      const expectedType2: number = result.dehydrated.bigNumber\n      const expectedType3: number = result.dehydrated.number\n    })\n\n    it('should dehydrate Date to string', async () => {\n      const now = sql<Date | string>`current_timestamp`.as('date')\n\n      const result = await db\n        .selectNoFrom([\n          now,\n          jsonObjectFrom(db.selectNoFrom([now]))\n            .$notNull()\n            .as('dehydrated'),\n        ])\n        .executeTakeFirstOrThrow()\n\n      expect(typeof result.date).to.equal(\n        {\n          postgres: 'object',\n          mysql: 'object',\n          mssql: 'object',\n          sqlite: 'string',\n        }[dialect],\n      )\n      if (dialect !== 'sqlite') {\n        expect(result.date instanceof Date).to.equal(true)\n      }\n      expect(typeof result.dehydrated.date).to.equal('string')\n\n      const expectedType0: Date | string = result.date\n      const expectedType1: string = result.dehydrated.date\n    })\n\n    it('should dehydrate Buffer to string in jsonArrayFrom', async () => {\n      const buffer = {\n        postgres: sql<Buffer>`'\\\\xDEADBEEF'::bytea`,\n        mysql: sql<Buffer>`UNHEX('DEADBEEF')`,\n        mssql: sql<Buffer>`CAST('DEADBEEF' AS VARBINARY)`,\n        sqlite: sql<Buffer>`X'DEADBEEF'`,\n      }[dialect].as('buffer')\n\n      const result = await db\n        .selectNoFrom([\n          buffer,\n          jsonObjectFrom(\n            db.selectNoFrom([\n              dialect === 'sqlite'\n                ? expressionBuilder()\n                    .cast<string>(buffer.expression, 'text')\n                    .as('buffer')\n                : buffer,\n            ]),\n          )\n            .$notNull()\n            .as('dehydrated'),\n        ])\n        .executeTakeFirstOrThrow()\n\n      expect(typeof result.buffer).to.equal('object')\n      expect(Buffer.isBuffer(result.buffer)).to.equal(true)\n      expect(typeof result.dehydrated.buffer).to.equal('string')\n\n      const expectedType0: Buffer = result.buffer\n      const expectedType1: string = result.dehydrated.buffer\n    })\n  })\n\n  function toJson<T>(obj: T): RawBuilder<T> {\n    return sql`${JSON.stringify(obj)}`\n  }\n}\n"
  },
  {
    "path": "test/node/src/log-once.test.ts",
    "content": "import { expect } from 'chai'\nimport { createSandbox, SinonSpy } from 'sinon'\nimport { logOnce } from '../../..'\n\ndescribe('logOnce', () => {\n  let logSpy: SinonSpy\n  const sandbox = createSandbox()\n\n  before(() => {\n    logSpy = sandbox.stub(console, 'log')\n  })\n\n  after(() => {\n    sandbox.restore()\n  })\n\n  it('should log each message once.', () => {\n    const message = 'Kysely is awesome!'\n    const message2 = 'Type-safety is everything!'\n\n    logOnce(message)\n    logOnce(message)\n    logOnce(message2)\n    logOnce(message2)\n    logOnce(message)\n\n    expect(logSpy.calledTwice).to.be.true\n    expect(logSpy.getCall(0).args[0]).to.equal(message)\n    expect(logSpy.getCall(1).args[0]).to.equal(message2)\n  })\n})\n"
  },
  {
    "path": "test/node/src/logging.test.ts",
    "content": "import { SinonSandbox, SinonSpy, createSandbox } from 'sinon'\nimport { Database, expect } from './test-setup'\nimport {\n  DatabaseConnection,\n  Driver,\n  DummyDriver,\n  Kysely,\n  LogConfig,\n  PostgresDialect,\n} from '../../..'\n\ndescribe('logging', () => {\n  let sandbox: SinonSandbox\n  let errorSpy: SinonSpy\n  let logSpy: SinonSpy\n\n  beforeEach(() => {\n    sandbox = createSandbox()\n    errorSpy = sandbox.stub(console, 'error')\n    logSpy = sandbox.stub(console, 'log')\n  })\n\n  afterEach(() => {\n    sandbox.restore()\n  })\n\n  describe('when query execution succeeds', () => {\n    describe('when query logging is disabled', () => {\n      describe('when error logging is disabled', () => {\n        const db = getKysely([])\n\n        it('should not log query', async () => {\n          await run(db)\n          expect(logSpy.called).to.be.false\n        })\n\n        it('should not log error', async () => {\n          await run(db)\n          expect(errorSpy.called).to.be.false\n        })\n      })\n\n      describe('when error logging is enabled', () => {\n        const db = getKysely(['error'])\n\n        it('should not log query', async () => {\n          await run(db)\n          expect(logSpy.called).to.be.false\n        })\n\n        it('should not log error', async () => {\n          await run(db)\n          expect(errorSpy.called).to.be.false\n        })\n      })\n    })\n\n    describe('when query logging is enabled', () => {\n      describe('when error logging is disabled', () => {\n        const db = getKysely(['query'])\n\n        it('should log query', async () => {\n          await run(db)\n          expect(logSpy.callCount).to.equal(4)\n          expect(logSpy.args[0][0]).to.match(/^kysely:query: .* \"person\"$/)\n          expect(logSpy.args[2][0]).to.match(/^kysely:query:stream: .* \"pet\"$/)\n        })\n\n        it('should not log error', async () => {\n          await run(db)\n          expect(errorSpy.called).to.be.false\n        })\n      })\n\n      describe('when error logging is enabled', () => {\n        const db = getKysely(['query', 'error'])\n\n        it('should log query', async () => {\n          await run(db)\n          expect(logSpy.callCount).to.equal(4)\n          expect(logSpy.args[0][0]).to.match(/^kysely:query: .* \"person\"$/)\n          expect(logSpy.args[2][0]).to.match(/^kysely:query:stream: .* \"pet\"$/)\n        })\n\n        it('should not log error', async () => {\n          await run(db)\n          expect(errorSpy.called).to.be.false\n        })\n      })\n    })\n  })\n\n  describe('when query execution fails', () => {\n    const executeQuery = () => Promise.reject('oops')\n    const streamQuery = async function* () {\n      throw 'oops'\n    }\n\n    describe('when query logging is disabled', () => {\n      describe('when error logging is disabled', () => {\n        const db = getKysely([], executeQuery, streamQuery)\n\n        it('should not log query', async () => {\n          await run(db)\n          expect(logSpy.called).to.be.false\n        })\n\n        it('should not log error', async () => {\n          await run(db)\n          expect(errorSpy.called).to.be.false\n        })\n      })\n\n      describe('when error logging is enabled', () => {\n        const db = getKysely(['error'], executeQuery, streamQuery)\n\n        it('should not log query', async () => {\n          await run(db)\n          expect(logSpy.called).to.be.false\n        })\n\n        it('should log error', async () => {\n          await run(db)\n          expect(errorSpy.callCount).to.equal(2)\n          expect(errorSpy.args[0][0]).to.match(/^kysely:error: .+ \\\\\"person\\\\\"/)\n          expect(errorSpy.args[1][0]).to.match(/^kysely:error: .+ \\\\\"pet\\\\\"/)\n        })\n      })\n    })\n\n    describe('when query logging is enabled', () => {\n      describe('when error logging is disabled', () => {\n        const db = getKysely(['query'], executeQuery, streamQuery)\n\n        it('should not log query', async () => {\n          await run(db)\n          expect(logSpy.called).to.be.false\n        })\n\n        it('should not log error', async () => {\n          await run(db)\n          expect(errorSpy.called).to.be.false\n        })\n      })\n\n      describe('when error logging is enabled', () => {\n        const db = getKysely(['query', 'error'], executeQuery, streamQuery)\n\n        it('should not log query', async () => {\n          await run(db)\n          expect(logSpy.called).to.be.false\n        })\n\n        it('should log error', async () => {\n          await run(db)\n          expect(errorSpy.callCount).to.equal(2)\n          expect(errorSpy.args[0][0]).to.match(/^kysely:error: .+ \\\\\"person\\\\\"/)\n          expect(errorSpy.args[1][0]).to.match(/^kysely:error: .+ \\\\\"pet\\\\\"/)\n        })\n      })\n    })\n  })\n})\n\nfunction getKysely(\n  log: LogConfig,\n  executeQuery: DatabaseConnection['executeQuery'] = () =>\n    Promise.resolve({ rows: [] }),\n  streamQuery: DatabaseConnection['streamQuery'] = async function* () {\n    return\n  },\n): Kysely<Database> {\n  return new Kysely({\n    dialect: new (class extends PostgresDialect {\n      constructor() {\n        super({ pool: {} as any })\n      }\n      createDriver(): Driver {\n        return new (class extends DummyDriver {\n          acquireConnection(): Promise<DatabaseConnection> {\n            return Promise.resolve({ executeQuery, streamQuery })\n          }\n        })()\n      }\n    })(),\n    log,\n  })\n}\n\nasync function run(db: Kysely<Database>) {\n  try {\n    await db.selectFrom('person').selectAll().execute()\n  } catch (err) {}\n\n  try {\n    for await (const _ of db.selectFrom('pet').selectAll().stream()) {\n      // noop\n    }\n  } catch (err) {}\n}\n"
  },
  {
    "path": "test/node/src/merge.test.ts",
    "content": "import { MergeResult, sql } from '../../..'\nimport { mergeAction } from '../../../helpers/postgres'\nimport {\n  DIALECTS,\n  NOT_SUPPORTED,\n  TestContext,\n  clearDatabase,\n  destroyTest,\n  expect,\n  initTest,\n  insertDefaultDataSet,\n  testSql,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS.filter(\n  (dialect) => dialect === 'postgres' || dialect === 'mssql',\n)) {\n  describe(`merge (${dialect})`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    describe('using', () => {\n      it('should perform a merge...using table simple on...when matched then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .using('pet', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete;',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(3n)\n      })\n\n      it('should add a modifyEnd clause to the query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .using('pet', 'pet.owner_id', 'person.id')\n          .modifyEnd(sql.raw('-- this is a comment'))\n          .whenMatched()\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete -- this is a comment',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete -- this is a comment;',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n      })\n\n      it('should perform a merge...using table alias simple on alias...when matched then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person as pr')\n          .using('pet as pt', 'pt.owner_id', 'pr.id')\n          .whenMatched()\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" as \"pr\" using \"pet\" as \"pt\" on \"pt\".\"owner_id\" = \"pr\".\"id\" when matched then delete',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" as \"pr\" using \"pet\" as \"pt\" on \"pt\".\"owner_id\" = \"pr\".\"id\" when matched then delete;',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(3n)\n      })\n\n      it('should perform a merge...using table complex on...when matched then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .using('pet', (on) =>\n            on\n              .onRef('pet.owner_id', '=', 'person.id')\n              .on('pet.name', '=', 'Lucky'),\n          )\n          .whenMatched()\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" and \"pet\".\"name\" = $1 when matched then delete',\n            parameters: ['Lucky'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" and \"pet\".\"name\" = @1 when matched then delete;',\n            parameters: ['Lucky'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(0n)\n      })\n\n      it('should perform a merge...using subquery simple on...when matched then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .using(\n            ctx.db\n              .selectFrom('pet')\n              .select('owner_id')\n              .where('name', '=', 'Lucky')\n              .as('pet'),\n            'pet.owner_id',\n            'person.id',\n          )\n          .whenMatched()\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" using (select \"owner_id\" from \"pet\" where \"name\" = $1) as \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete',\n            parameters: ['Lucky'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" using (select \"owner_id\" from \"pet\" where \"name\" = @1) as \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete;',\n            parameters: ['Lucky'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n      })\n    })\n\n    describe('whenMatched', () => {\n      it('should perform a merge...using table simple on...when matched and simple binary then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .using('pet', 'pet.owner_id', 'person.id')\n          .whenMatchedAnd('person.gender', '=', 'female')\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched and \"person\".\"gender\" = $1 then delete',\n            parameters: ['female'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched and \"person\".\"gender\" = @1 then delete;',\n            parameters: ['female'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(1n)\n      })\n\n      it('should perform a merge...using table simple on...when matched and simple binary cross ref then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .using('pet', 'pet.owner_id', 'person.id')\n          .whenMatchedAndRef('person.first_name', '=', 'pet.name')\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched and \"person\".\"first_name\" = \"pet\".\"name\" then delete',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched and \"person\".\"first_name\" = \"pet\".\"name\" then delete;',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(0n)\n      })\n\n      it('should perform a merge...using table simple on...when matched and complex and then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .using('pet', 'pet.owner_id', 'person.id')\n          .whenMatchedAnd((eb) =>\n            eb('person.gender', '=', 'female').and(\n              'person.first_name',\n              '=',\n              eb.ref('pet.name'),\n            ),\n          )\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched and (\"person\".\"gender\" = $1 and \"person\".\"first_name\" = \"pet\".\"name\") then delete',\n            parameters: ['female'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched and (\"person\".\"gender\" = @1 and \"person\".\"first_name\" = \"pet\".\"name\") then delete;',\n            parameters: ['female'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(0n)\n      })\n\n      it('should perform a merge...using table simple on...when matched and complex or then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .using('pet', 'pet.owner_id', 'person.id')\n          .whenMatchedAnd((eb) =>\n            eb('person.gender', '=', 'female').or(\n              'person.first_name',\n              '=',\n              eb.ref('pet.name'),\n            ),\n          )\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched and (\"person\".\"gender\" = $1 or \"person\".\"first_name\" = \"pet\".\"name\") then delete',\n            parameters: ['female'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched and (\"person\".\"gender\" = @1 or \"person\".\"first_name\" = \"pet\".\"name\") then delete;',\n            parameters: ['female'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(1n)\n      })\n\n      if (dialect === 'postgres') {\n        it('should perform a merge...using table...when matched then do nothing query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', 'pet.owner_id', 'person.id')\n            .whenMatched()\n            .thenDoNothing()\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then do nothing',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(0n)\n        })\n      }\n\n      describe('update', () => {\n        it('should perform a merge...using table simple on...when matched then update set object query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', 'pet.owner_id', 'person.id')\n            .whenMatched()\n            .thenUpdateSet({\n              middle_name: 'pet owner',\n            })\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"middle_name\" = $1',\n              parameters: ['pet owner'],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"middle_name\" = @1;',\n              parameters: ['pet owner'],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(3n)\n        })\n\n        it('should perform a merge...using table simple on...when matched then update set object ref query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', 'pet.owner_id', 'person.id')\n            .whenMatched()\n            .thenUpdateSet((eb) => ({\n              first_name: eb.ref('person.last_name'),\n              middle_name: eb.ref('pet.name'),\n            }))\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"first_name\" = \"person\".\"last_name\", \"middle_name\" = \"pet\".\"name\"',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"first_name\" = \"person\".\"last_name\", \"middle_name\" = \"pet\".\"name\";',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(3n)\n        })\n\n        it('should perform a merge...using table simple on...when matched then update set column query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', 'pet.owner_id', 'person.id')\n            .whenMatched()\n            .thenUpdateSet('middle_name', 'pet owner')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"middle_name\" = $1',\n              parameters: ['pet owner'],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"middle_name\" = @1;',\n              parameters: ['pet owner'],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(3n)\n        })\n\n        it('should perform a merge...using table simple on...when matched then update set column ref query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', 'pet.owner_id', 'person.id')\n            .whenMatched()\n            .thenUpdateSet('first_name', (eb) => eb.ref('person.last_name'))\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"first_name\" = \"person\".\"last_name\"',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"first_name\" = \"person\".\"last_name\";',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(3n)\n        })\n\n        it('should perform a merge...using table simple on...when matched then update set column cross ref query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', 'pet.owner_id', 'person.id')\n            .whenMatched()\n            .thenUpdateSet('middle_name', (eb) => eb.ref('pet.name'))\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"middle_name\" = \"pet\".\"name\"',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"middle_name\" = \"pet\".\"name\";',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(3n)\n        })\n\n        it('should perform a merge...using table simple on...when matched then update set complex query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', 'pet.owner_id', 'person.id')\n            .whenMatched()\n            .thenUpdate((ub) =>\n              ub\n                .set('first_name', (eb) => eb.ref('person.last_name'))\n                .set('middle_name', (eb) => eb.ref('pet.name'))\n                .set({\n                  marital_status: 'single',\n                }),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"first_name\" = \"person\".\"last_name\", \"middle_name\" = \"pet\".\"name\", \"marital_status\" = $1',\n              parameters: ['single'],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"first_name\" = \"person\".\"last_name\", \"middle_name\" = \"pet\".\"name\", \"marital_status\" = @1;',\n              parameters: ['single'],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(3n)\n        })\n      })\n    })\n\n    describe('whenNotMatched', () => {\n      if (dialect === 'postgres') {\n        it('should perform a merge...using table simple on...when not matched then do nothing query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', 'pet.owner_id', 'person.id')\n            .whenNotMatched()\n            .thenDoNothing()\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched then do nothing',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(0n)\n        })\n      }\n\n      describe('insert', () => {\n        it('should perform a merge...using table complex on...when not matched then insert values query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', (on) =>\n              on\n                .onRef('pet.owner_id', '=', 'person.id')\n                .on('pet.name', '=', 'NO_SUCH_PET_NAME'),\n            )\n            .whenNotMatched()\n            .thenInsertValues({\n              gender: 'male',\n              first_name: 'Dingo',\n              middle_name: 'the',\n              last_name: 'Dog',\n            })\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" and \"pet\".\"name\" = $1 when not matched then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values ($2, $3, $4, $5)',\n              parameters: ['NO_SUCH_PET_NAME', 'male', 'Dingo', 'the', 'Dog'],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" and \"pet\".\"name\" = @1 when not matched then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values (@2, @3, @4, @5);',\n              parameters: ['NO_SUCH_PET_NAME', 'male', 'Dingo', 'the', 'Dog'],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(3n)\n        })\n\n        describe('And', () => {\n          it('should perform a merge...using table simple on...when not matched and simple binary then insert values query', async () => {\n            const query = ctx.db\n              .mergeInto('person')\n              .using('pet', 'pet.owner_id', 'person.id')\n              .whenNotMatchedAnd('pet.name', '=', 'Dingo')\n              .thenInsertValues({\n                gender: 'male',\n                first_name: 'Dingo',\n                middle_name: 'the',\n                last_name: 'Dog',\n              })\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched and \"pet\".\"name\" = $1 then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values ($2, $3, $4, $5)',\n                parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: {\n                sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched and \"pet\".\"name\" = @1 then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values (@2, @3, @4, @5);',\n                parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            const result = await query.executeTakeFirstOrThrow()\n\n            expect(result).to.be.instanceOf(MergeResult)\n            expect(result.numChangedRows).to.equal(0n)\n          })\n\n          it('should perform a merge...using table simple on...when not matched and simple binary ref then insert values query', async () => {\n            const query = ctx.db\n              .mergeInto('person')\n              .using('pet', 'pet.owner_id', 'person.id')\n              .whenNotMatchedAndRef('pet.name', '=', 'pet.species')\n              .thenInsertValues({\n                gender: 'male',\n                first_name: 'Dingo',\n                middle_name: 'the',\n                last_name: 'Dog',\n              })\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched and \"pet\".\"name\" = \"pet\".\"species\" then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values ($1, $2, $3, $4)',\n                parameters: ['male', 'Dingo', 'the', 'Dog'],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: {\n                sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched and \"pet\".\"name\" = \"pet\".\"species\" then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values (@1, @2, @3, @4);',\n                parameters: ['male', 'Dingo', 'the', 'Dog'],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            const result = await query.executeTakeFirstOrThrow()\n\n            expect(result).to.be.instanceOf(MergeResult)\n            expect(result.numChangedRows).to.equal(0n)\n          })\n\n          it('should perform a merge...using table simple on...when not matched and complex and then insert values query', async () => {\n            const query = ctx.db\n              .mergeInto('person')\n              .using('pet', 'pet.owner_id', 'person.id')\n              .whenNotMatchedAnd((eb) =>\n                eb('pet.name', '=', 'Dingo').and(\n                  'pet.name',\n                  '=',\n                  eb.ref('pet.name'),\n                ),\n              )\n              .thenInsertValues({\n                gender: 'male',\n                first_name: 'Dingo',\n                middle_name: 'the',\n                last_name: 'Dog',\n              })\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched and (\"pet\".\"name\" = $1 and \"pet\".\"name\" = \"pet\".\"name\") then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values ($2, $3, $4, $5)',\n                parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: {\n                sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched and (\"pet\".\"name\" = @1 and \"pet\".\"name\" = \"pet\".\"name\") then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values (@2, @3, @4, @5);',\n                parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            const result = await query.executeTakeFirstOrThrow()\n\n            expect(result).to.be.instanceOf(MergeResult)\n            expect(result.numChangedRows).to.equal(0n)\n          })\n\n          it('should perform a merge...using table simple on...when not matched and complex or then insert values query', async () => {\n            const query = ctx.db\n              .mergeInto('person')\n              .using('pet', 'pet.owner_id', 'person.id')\n              .whenNotMatchedAnd((eb) =>\n                eb('pet.name', '=', 'Dingo').or(\n                  'pet.name',\n                  '=',\n                  eb.ref('pet.name'),\n                ),\n              )\n              .thenInsertValues({\n                gender: 'male',\n                first_name: 'Dingo',\n                middle_name: 'the',\n                last_name: 'Dog',\n              })\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched and (\"pet\".\"name\" = $1 or \"pet\".\"name\" = \"pet\".\"name\") then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values ($2, $3, $4, $5)',\n                parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: {\n                sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched and (\"pet\".\"name\" = @1 or \"pet\".\"name\" = \"pet\".\"name\") then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values (@2, @3, @4, @5);',\n                parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            const result = await query.executeTakeFirstOrThrow()\n\n            expect(result).to.be.instanceOf(MergeResult)\n            expect(result.numChangedRows).to.equal(0n)\n          })\n        })\n\n        it('should perform a merge...using table complex on...when not matched then insert values cross ref query', async () => {\n          const query = ctx.db\n            .mergeInto('person')\n            .using('pet', (on) => on.on('pet.owner_id', 'is', null))\n            .whenNotMatched()\n            .thenInsertValues((eb) => ({\n              gender: 'other',\n              first_name: eb.ref('pet.name'),\n              middle_name: 'the',\n              last_name: eb.ref('pet.species'),\n            }))\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" is null when not matched then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values ($1, \"pet\".\"name\", $2, \"pet\".\"species\")',\n              parameters: ['other', 'the'],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" is null when not matched then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values (@1, \"pet\".\"name\", @2, \"pet\".\"species\");',\n              parameters: ['other', 'the'],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.executeTakeFirstOrThrow()\n\n          expect(result).to.be.instanceOf(MergeResult)\n          expect(result.numChangedRows).to.equal(3n)\n        })\n      })\n\n      if (dialect === 'mssql') {\n        describe('BySource', () => {\n          it('should perform a merge...using table simple on...when not matched by source then delete query', async () => {\n            const query = ctx.db\n              .mergeInto('person')\n              .using('pet', 'pet.owner_id', 'person.id')\n              .whenNotMatchedBySource()\n              .thenDelete()\n\n            testSql(query, dialect, {\n              postgres: NOT_SUPPORTED,\n              mysql: NOT_SUPPORTED,\n              mssql: {\n                sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source then delete;',\n                parameters: [],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            const result = await query.executeTakeFirstOrThrow()\n\n            expect(result).to.be.instanceOf(MergeResult)\n            expect(result.numChangedRows).to.equal(0n)\n          })\n\n          describe('And', () => {\n            it('should perform a merge...using table simple on...when not matched by source and simple binary then delete query', async () => {\n              const query = ctx.db\n                .mergeInto('person')\n                .using('pet', 'pet.owner_id', 'person.id')\n                .whenNotMatchedBySourceAnd('person.first_name', '=', 'Jennifer')\n                .thenDelete()\n\n              testSql(query, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source and \"person\".\"first_name\" = @1 then delete;',\n                  parameters: ['Jennifer'],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              const result = await query.executeTakeFirstOrThrow()\n\n              expect(result).to.be.instanceOf(MergeResult)\n              expect(result.numChangedRows).to.equal(0n)\n            })\n\n            it('should perform a merge...using table simple on...when not matched by source and simple binary ref then delete query', async () => {\n              const query = ctx.db\n                .mergeInto('person')\n                .using('pet', 'pet.owner_id', 'person.id')\n                .whenNotMatchedBySourceAndRef(\n                  'person.first_name',\n                  '=',\n                  'person.last_name',\n                )\n                .thenDelete()\n\n              testSql(query, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source and \"person\".\"first_name\" = \"person\".\"last_name\" then delete;',\n                  parameters: [],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              const result = await query.executeTakeFirstOrThrow()\n\n              expect(result).to.be.instanceOf(MergeResult)\n              expect(result.numChangedRows).to.equal(0n)\n            })\n\n            it('should perform a merge...using table simple on...when not matched by source and complex and then delete query', async () => {\n              const query = ctx.db\n                .mergeInto('person')\n                .using('pet', 'pet.owner_id', 'person.id')\n                .whenNotMatchedBySourceAnd((eb) =>\n                  eb('person.gender', '=', 'female').and(\n                    'person.first_name',\n                    '=',\n                    eb.ref('person.last_name'),\n                  ),\n                )\n                .thenDelete()\n\n              testSql(query, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source and (\"person\".\"gender\" = @1 and \"person\".\"first_name\" = \"person\".\"last_name\") then delete;',\n                  parameters: ['female'],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              const result = await query.executeTakeFirstOrThrow()\n\n              expect(result).to.be.instanceOf(MergeResult)\n              expect(result.numChangedRows).to.equal(0n)\n            })\n\n            it('should perform a merge...using table simple on...when not matched by source and complex or then delete query', async () => {\n              const query = ctx.db\n                .mergeInto('person')\n                .using('pet', 'pet.owner_id', 'person.id')\n                .whenNotMatchedBySourceAnd((eb) =>\n                  eb('person.gender', '=', 'female').or(\n                    'person.first_name',\n                    '=',\n                    eb.ref('person.last_name'),\n                  ),\n                )\n                .thenDelete()\n\n              testSql(query, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source and (\"person\".\"gender\" = @1 or \"person\".\"first_name\" = \"person\".\"last_name\") then delete;',\n                  parameters: ['female'],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              const result = await query.executeTakeFirstOrThrow()\n\n              expect(result).to.be.instanceOf(MergeResult)\n              expect(result.numChangedRows).to.equal(0n)\n            })\n          })\n\n          describe('update', () => {\n            it('should perform a merge...using table simple on...when not matched by source then update set object query', async () => {\n              const query = ctx.db\n                .mergeInto('person')\n                .using('pet', 'pet.owner_id', 'person.id')\n                .whenNotMatchedBySource()\n                .thenUpdateSet({\n                  middle_name: 'pet owner',\n                })\n\n              testSql(query, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source then update set \"middle_name\" = @1;',\n                  parameters: ['pet owner'],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              const result = await query.executeTakeFirstOrThrow()\n\n              expect(result).to.be.instanceOf(MergeResult)\n              expect(result.numChangedRows).to.equal(0n)\n            })\n\n            it('should perform a merge...using table simple on...when not matched by source then update set object ref query', async () => {\n              const query = ctx.db\n                .mergeInto('person')\n                .using('pet', 'pet.owner_id', 'person.id')\n                .whenNotMatchedBySource()\n                .thenUpdateSet((eb) => ({\n                  first_name: eb.ref('person.last_name'),\n                }))\n\n              testSql(query, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source then update set \"first_name\" = \"person\".\"last_name\";',\n                  parameters: [],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              const result = await query.executeTakeFirstOrThrow()\n\n              expect(result).to.be.instanceOf(MergeResult)\n              expect(result.numChangedRows).to.equal(0n)\n            })\n\n            it('should perform a merge...using table simple on...when not matched by source then update set column query', async () => {\n              const query = ctx.db\n                .mergeInto('person')\n                .using('pet', 'pet.owner_id', 'person.id')\n                .whenNotMatchedBySource()\n                .thenUpdateSet('middle_name', 'pet owner')\n\n              testSql(query, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source then update set \"middle_name\" = @1;',\n                  parameters: ['pet owner'],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              const result = await query.executeTakeFirstOrThrow()\n\n              expect(result).to.be.instanceOf(MergeResult)\n              expect(result.numChangedRows).to.equal(0n)\n            })\n\n            it('should perform a merge...using table simple on...when not matched by source then update set column ref query', async () => {\n              const query = ctx.db\n                .mergeInto('person')\n                .using('pet', 'pet.owner_id', 'person.id')\n                .whenNotMatchedBySource()\n                .thenUpdateSet('first_name', (eb) => eb.ref('person.last_name'))\n\n              testSql(query, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source then update set \"first_name\" = \"person\".\"last_name\";',\n                  parameters: [],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              const result = await query.executeTakeFirstOrThrow()\n\n              expect(result).to.be.instanceOf(MergeResult)\n              expect(result.numChangedRows).to.equal(0n)\n            })\n\n            it('should perform a merge...using table simple on...when not matched by source then update set complex query', async () => {\n              const query = ctx.db\n                .mergeInto('person')\n                .using('pet', 'pet.owner_id', 'person.id')\n                .whenNotMatchedBySource()\n                .thenUpdate((ub) =>\n                  ub\n                    .set('first_name', (eb) => eb.ref('person.last_name'))\n                    .set({\n                      marital_status: 'single',\n                    }),\n                )\n\n              testSql(query, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when not matched by source then update set \"first_name\" = \"person\".\"last_name\", \"marital_status\" = @1;',\n                  parameters: ['single'],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              const result = await query.executeTakeFirstOrThrow()\n\n              expect(result).to.be.instanceOf(MergeResult)\n              expect(result.numChangedRows).to.equal(0n)\n            })\n          })\n        })\n      }\n    })\n\n    describe('multiple whens', () => {\n      it('should perform a merge...using table simple on...when matched then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .using('pet', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenDelete()\n          .whenNotMatched()\n          .thenInsertValues((eb) => ({\n            gender: 'other',\n            first_name: eb.ref('pet.name'),\n            middle_name: 'the',\n            last_name: eb.ref('pet.species'),\n          }))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete when not matched then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values ($1, \"pet\".\"name\", $2, \"pet\".\"species\")',\n            parameters: ['other', 'the'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete when not matched then insert (\"gender\", \"first_name\", \"middle_name\", \"last_name\") values (@1, \"pet\".\"name\", @2, \"pet\".\"species\");',\n            parameters: ['other', 'the'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(3n)\n      })\n    })\n\n    if (dialect === 'postgres') {\n      it('should perform a merge...using table simple on...when matched then delete returning id query', async () => {\n        const expected = await ctx.db.selectFrom('pet').select('id').execute()\n\n        const query = ctx.db\n          .mergeInto('pet')\n          .using('person', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenDelete()\n          .returning('pet.id')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"pet\" using \"person\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete returning \"pet\".\"id\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.eql(expected)\n      })\n\n      it('should perform a merge...using table simple on...when matched then update set name returning {target}.name, {source}.first_name query', async () => {\n        const query = ctx.db\n          .mergeInto('pet')\n          .using('person', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenUpdateSet((eb) => ({\n            name: sql`${eb.ref('person.first_name')} || '''s pet'`,\n          }))\n          .returning([\n            'pet.name as pet_name',\n            'person.first_name as owner_name',\n          ])\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"pet\" using \"person\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"name\" = \"person\".\"first_name\" || \\'\\'\\'s pet\\' returning \"pet\".\"name\" as \"pet_name\", \"person\".\"first_name\" as \"owner_name\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.eql([\n          { owner_name: 'Jennifer', pet_name: \"Jennifer's pet\" },\n          { owner_name: 'Arnold', pet_name: \"Arnold's pet\" },\n          { owner_name: 'Sylvester', pet_name: \"Sylvester's pet\" },\n        ])\n      })\n\n      it('should perform a merge...using table simple on...when matched then delete returning * query', async () => {\n        const expected = await ctx.db\n          .selectFrom('pet')\n          .innerJoin('person', 'pet.owner_id', 'person.id')\n          .selectAll()\n          .execute()\n\n        const query = ctx.db\n          .mergeInto('pet')\n          .using('person', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenDelete()\n          .returningAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"pet\" using \"person\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete returning *',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.eql(expected)\n      })\n\n      it('should perform a merge...using table simple on...when matched then delete returning {target}.* query', async () => {\n        const expected = await ctx.db.selectFrom('pet').selectAll().execute()\n\n        const query = ctx.db\n          .mergeInto('pet')\n          .using('person', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenDelete()\n          .returningAll('pet')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"pet\" using \"person\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete returning \"pet\".*',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.eql(expected)\n      })\n\n      it('should perform a merge...using table simple on...when matched then delete returning {source}.* query', async () => {\n        const expected = await ctx.db\n          .selectFrom('pet')\n          .innerJoin('person', 'pet.owner_id', 'person.id')\n          .selectAll('person')\n          .execute()\n\n        const query = ctx.db\n          .mergeInto('pet')\n          .using('person', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenDelete()\n          .returningAll('person')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"pet\" using \"person\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete returning \"person\".*',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.eql(expected)\n      })\n\n      it('should perform a merge...using table simple on...when matched then delete returning merge_action(), {target}.name', async () => {\n        await ctx.db.connection().execute(async (db) => {\n          await ctx.db\n            .insertInto('person')\n            .values({ first_name: 'Moshe', gender: 'other' })\n            .execute()\n\n          await sql`SET session_replication_role = 'replica'`.execute(db)\n          await db\n            .insertInto('pet')\n            .values({\n              name: 'Ralph',\n              owner_id: 9999,\n              species: 'hamster',\n            })\n            .execute()\n          await sql`SET session_replication_role = 'origin'`.execute(db)\n        })\n\n        const query = ctx.db\n          .mergeInto('pet')\n          .using('person', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenUpdateSet(\n            'name',\n            (eb) => sql`${eb.ref('person.first_name')} || '''s pet'`,\n          )\n          .whenNotMatched()\n          .thenInsertValues((eb) => ({\n            name: sql`${eb.ref('person.first_name')} || '''s pet'`,\n            owner_id: eb.ref('person.id'),\n            species: 'hamster',\n          }))\n          .whenNotMatchedBySource()\n          .thenDelete()\n          .returning([mergeAction().as('action'), 'pet.name'])\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"pet\" using \"person\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"name\" = \"person\".\"first_name\" || \\'\\'\\'s pet\\' when not matched then insert (\"name\", \"owner_id\", \"species\") values (\"person\".\"first_name\" || \\'\\'\\'s pet\\', \"person\".\"id\", $1) when not matched by source then delete returning merge_action() as \"action\", \"pet\".\"name\"',\n            parameters: ['hamster'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.eql([\n          { action: 'UPDATE', name: \"Jennifer's pet\" },\n          { action: 'UPDATE', name: \"Arnold's pet\" },\n          { action: 'UPDATE', name: \"Sylvester's pet\" },\n          { action: 'DELETE', name: 'Ralph' },\n          { action: 'INSERT', name: \"Moshe's pet\" },\n        ])\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should perform a merge top...using table simple on...when matched then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .top(1)\n          .using('pet', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge top(1) into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete;',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(1n)\n      })\n\n      it('should perform a merge top percent...using table simple on...when matched then delete query', async () => {\n        const query = ctx.db\n          .mergeInto('person')\n          .top(50, 'percent')\n          .using('pet', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge top(50) percent into \"person\" using \"pet\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete;',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result).to.be.instanceOf(MergeResult)\n        expect(result.numChangedRows).to.equal(2n)\n      })\n\n      it('should perform a merge...using table simple on...when matched then delete output id query', async () => {\n        const expected = await ctx.db.selectFrom('pet').select('id').execute()\n\n        const query = ctx.db\n          .mergeInto('pet')\n          .using('person', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenDelete()\n          .output('deleted.id')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"pet\" using \"person\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then delete output \"deleted\".\"id\";',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.eql(expected)\n      })\n\n      it('should perform a merge...using table simple on...when matched then update set name output deleted.name, inserted.name query', async () => {\n        const query = ctx.db\n          .mergeInto('pet')\n          .using('person', 'pet.owner_id', 'person.id')\n          .whenMatched()\n          .thenUpdateSet((eb) => ({\n            name: sql`${eb.ref('person.first_name')} + '''s pet'`,\n          }))\n          .output(['deleted.name as old_name', 'inserted.name as new_name'])\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"pet\" using \"person\" on \"pet\".\"owner_id\" = \"person\".\"id\" when matched then update set \"name\" = \"person\".\"first_name\" + \\'\\'\\'s pet\\' output \"deleted\".\"name\" as \"old_name\", \"inserted\".\"name\" as \"new_name\";',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.eql([\n          { old_name: 'Catto', new_name: \"Jennifer's pet\" },\n          { old_name: 'Doggo', new_name: \"Arnold's pet\" },\n          { old_name: 'Hammo', new_name: \"Sylvester's pet\" },\n        ])\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/migration.test.ts",
    "content": "import * as path from 'path'\nimport { promises as fs } from 'fs'\n\nimport {\n  FileMigrationProvider,\n  Migration,\n  MigrationResultSet,\n  DEFAULT_MIGRATION_LOCK_TABLE,\n  DEFAULT_MIGRATION_TABLE,\n  Migrator,\n  NO_MIGRATIONS,\n  MigratorProps,\n  type QueryExecutor,\n  type Kysely,\n} from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  expect,\n  initTest,\n  TestContext,\n  DIALECTS,\n  type Database,\n} from './test-setup.js'\nimport { createSandbox, type SinonSpy } from 'sinon'\n\nconst CUSTOM_MIGRATION_SCHEMA = 'migrate'\nconst CUSTOM_MIGRATION_TABLE = 'custom_migrations'\nconst CUSTOM_MIGRATION_LOCK_TABLE = 'custom_migrations_lock'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: migration`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n      await deleteMigrationTables()\n    })\n\n    afterEach(async () => {\n      await deleteMigrationTables()\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    describe('getMigrations', () => {\n      it('should get migrations', async () => {\n        const [migrator] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration3',\n        ])\n\n        const migrations1 = await migrator.getMigrations()\n        expect(migrations1).to.have.length(3)\n        expect(migrations1[0].name).to.equal('migration1')\n        expect(migrations1[0].executedAt).to.equal(undefined)\n        expect(migrations1[1].name).to.equal('migration2')\n        expect(migrations1[1].executedAt).to.equal(undefined)\n        expect(migrations1[2].name).to.equal('migration3')\n        expect(migrations1[2].executedAt).to.equal(undefined)\n\n        await migrator.migrateTo('migration2')\n\n        const migrations2 = await migrator.getMigrations()\n        expect(migrations2).to.have.length(3)\n        expect(migrations2[0].name).to.equal('migration1')\n        expect(migrations2[0].executedAt).to.be.instanceOf(Date)\n        expect(migrations2[1].name).to.equal('migration2')\n        expect(migrations2[1].executedAt).to.be.instanceOf(Date)\n        expect(migrations2[2].name).to.equal('migration3')\n        expect(migrations2[2].executedAt).to.equal(undefined)\n      })\n    })\n\n    describe('migrateToLatest', () => {\n      it('should run all unexecuted migrations', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations([\n          'migration1',\n          'migration2',\n        ])\n\n        const { results: results1 } = await migrator1.migrateToLatest()\n\n        const [migrator2, executedUpMethods2] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration3',\n          'migration4',\n        ])\n\n        const { results: results2 } = await migrator2.migrateToLatest()\n\n        expect(results1).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(results2).to.eql([\n          { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration4', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(executedUpMethods1).to.eql(['migration1', 'migration2'])\n        expect(executedUpMethods2).to.eql(['migration3', 'migration4'])\n      })\n\n      it('should return an error if a new migration is added before the last executed one', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations([\n          'migration1',\n          'migration3',\n        ])\n\n        await migrator1.migrateToLatest()\n\n        const [migrator2, executedUpMethods2] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration3',\n        ])\n\n        const { error } = await migrator2.migrateToLatest()\n\n        expect(error).to.be.an.instanceOf(Error)\n        expect(getMessage(error)).to.eql(\n          'corrupted migrations: expected previously executed migration migration3 to be at index 1 but migration2 was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.',\n        )\n\n        expect(executedUpMethods1).to.eql(['migration1', 'migration3'])\n        expect(executedUpMethods2).to.eql([])\n      })\n\n      it('should run a new migration added before the last executed one with allowUnorderedMigrations enabled', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations(\n          ['migration1', 'migration3'],\n          { allowUnorderedMigrations: true },\n        )\n\n        const { results: results1 } = await migrator1.migrateToLatest()\n\n        const [migrator2, executedUpMethods2] = createMigrations(\n          ['migration1', 'migration2', 'migration3', 'migration4'],\n          { allowUnorderedMigrations: true },\n        )\n\n        const { results: results2 } = await migrator2.migrateToLatest()\n\n        expect(results1).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(results2).to.eql([\n          { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration4', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(executedUpMethods1).to.eql(['migration1', 'migration3'])\n        expect(executedUpMethods2).to.eql(['migration2', 'migration4'])\n      })\n\n      it('should return an error if a previously executed migration is missing', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration3',\n        ])\n\n        await migrator1.migrateToLatest()\n\n        const [migrator2, executedUpMethods2] = createMigrations([\n          'migration2',\n          'migration3',\n          'migration4',\n        ])\n\n        const { error } = await migrator2.migrateToLatest()\n\n        expect(error).to.be.an.instanceOf(Error)\n        expect(getMessage(error)).to.eql(\n          'corrupted migrations: previously executed migration migration1 is missing',\n        )\n\n        expect(executedUpMethods1).to.eql([\n          'migration1',\n          'migration2',\n          'migration3',\n        ])\n        expect(executedUpMethods2).to.eql([])\n      })\n\n      it('should return an error if a the last executed migration is not found', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration3',\n        ])\n\n        const [migrator2, executedUpMethods2] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration4',\n        ])\n\n        await migrator1.migrateToLatest()\n        const { error } = await migrator2.migrateToLatest()\n\n        expect(error).to.be.an.instanceOf(Error)\n        expect(getMessage(error)).to.eql(\n          'corrupted migrations: previously executed migration migration3 is missing',\n        )\n\n        expect(executedUpMethods1).to.eql([\n          'migration1',\n          'migration2',\n          'migration3',\n        ])\n        expect(executedUpMethods2).to.eql([])\n      })\n\n      describe('with allowUnorderedMigrations', () => {\n        it('should return an error if a previously executed migration is missing', async () => {\n          const [migrator1, executedUpMethods1] = createMigrations(\n            ['migration1', 'migration2', 'migration3'],\n            { allowUnorderedMigrations: true },\n          )\n\n          await migrator1.migrateToLatest()\n\n          const [migrator2, executedUpMethods2] = createMigrations(\n            ['migration2', 'migration3', 'migration4'],\n            { allowUnorderedMigrations: true },\n          )\n\n          const { error } = await migrator2.migrateToLatest()\n\n          expect(error).to.be.an.instanceOf(Error)\n          expect(getMessage(error)).to.eql(\n            'corrupted migrations: previously executed migration migration1 is missing',\n          )\n\n          expect(executedUpMethods1).to.eql([\n            'migration1',\n            'migration2',\n            'migration3',\n          ])\n          expect(executedUpMethods2).to.eql([])\n        })\n\n        it('should return an error if a the last executed migration is not found', async () => {\n          const [migrator1, executedUpMethods1] = createMigrations(\n            ['migration1', 'migration2', 'migration3'],\n            { allowUnorderedMigrations: true },\n          )\n\n          const [migrator2, executedUpMethods2] = createMigrations(\n            ['migration1', 'migration2', 'migration4'],\n            { allowUnorderedMigrations: true },\n          )\n\n          await migrator1.migrateToLatest()\n          const { error } = await migrator2.migrateToLatest()\n\n          expect(error).to.be.an.instanceOf(Error)\n          expect(getMessage(error)).to.eql(\n            'corrupted migrations: previously executed migration migration3 is missing',\n          )\n\n          expect(executedUpMethods1).to.eql([\n            'migration1',\n            'migration2',\n            'migration3',\n          ])\n          expect(executedUpMethods2).to.eql([])\n        })\n      })\n\n      it('should return an error if one of the migrations fails', async () => {\n        const [migrator, executedUpMethods] = createMigrations([\n          'migration1',\n          { name: 'migration2', error: 'whoopsydaisy' },\n          'migration3',\n        ])\n\n        const { error, results } = await migrator.migrateToLatest()\n\n        expect(getMessage(error)).to.equal('whoopsydaisy')\n\n        expect(results).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration2', direction: 'Up', status: 'Error' },\n          {\n            migrationName: 'migration3',\n            direction: 'Up',\n            status: 'NotExecuted',\n          },\n        ])\n\n        expect(executedUpMethods).to.eql(['migration1'])\n      })\n\n      it('should work correctly when run in parallel', async () => {\n        const [migrator, executedUpMethods] = createMigrations([\n          'migration1',\n          'migration2',\n        ])\n\n        const promises: Promise<MigrationResultSet>[] = []\n        for (let i = 0; i < 100; ++i) {\n          promises.push(migrator.migrateToLatest())\n        }\n\n        await Promise.all(promises)\n        expect(executedUpMethods).to.eql(['migration1', 'migration2'])\n      })\n\n      describe('using folder of migration files', () => {\n        beforeEach(async () => {\n          await dropTestMigrationTables()\n        })\n\n        afterEach(async () => {\n          await dropTestMigrationTables()\n        })\n\n        it('should run migrations from a folder', async () => {\n          const migrator = new Migrator({\n            db: ctx.db,\n            provider: new FileMigrationProvider({\n              fs,\n              path,\n              migrationFolder: path.join(__dirname, 'test-migrations'),\n            }),\n          })\n\n          await migrator.migrateToLatest()\n\n          // The migrations should create two tables test1 and test2.\n          // Make sure they were correctly created.\n\n          expect(await doesTableExists('test1')).to.eql(true)\n          expect(await doesTableExists('test2')).to.eql(true)\n        })\n\n        async function dropTestMigrationTables(): Promise<void> {\n          await ctx.db.schema.dropTable('test2').ifExists().execute()\n          await ctx.db.schema.dropTable('test1').ifExists().execute()\n        }\n      })\n    })\n\n    describe('migrateTo', () => {\n      it('should migrate up to a specific migration', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration3',\n          'migration4',\n        ])\n\n        const { results: results1 } = await migrator1.migrateTo('migration2')\n\n        const [migrator2, executedUpMethods2] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration3',\n          'migration4',\n        ])\n\n        const { results: results2 } = await migrator2.migrateTo('migration3')\n\n        expect(results1).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(results2).to.eql([\n          { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(executedUpMethods1).to.eql(['migration1', 'migration2'])\n        expect(executedUpMethods2).to.eql(['migration3'])\n      })\n\n      it('should migrate all the way down', async () => {\n        const [migrator, executedUpMethods, executedDownMethods] =\n          createMigrations(['migration1', 'migration2', 'migration3'])\n\n        const { results: results1 } = await migrator.migrateToLatest()\n        const { results: results2 } = await migrator.migrateTo(NO_MIGRATIONS)\n\n        expect(results1).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(results2).to.eql([\n          { migrationName: 'migration3', direction: 'Down', status: 'Success' },\n          { migrationName: 'migration2', direction: 'Down', status: 'Success' },\n          { migrationName: 'migration1', direction: 'Down', status: 'Success' },\n        ])\n\n        expect(executedUpMethods).to.eql([\n          'migration1',\n          'migration2',\n          'migration3',\n        ])\n        expect(executedDownMethods).to.eql([\n          'migration3',\n          'migration2',\n          'migration1',\n        ])\n      })\n\n      it('should migrate all the way down with a foreign NO_MIGRATIONS object', async () => {\n        const [migrator, executedUpMethods, executedDownMethods] =\n          createMigrations(['migration1', 'migration2', 'migration3'])\n\n        const { results: results1 } = await migrator.migrateToLatest()\n        const { results: results2 } = await migrator.migrateTo({\n          __noMigrations__: true,\n        })\n\n        expect(results1).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(results2).to.eql([\n          { migrationName: 'migration3', direction: 'Down', status: 'Success' },\n          { migrationName: 'migration2', direction: 'Down', status: 'Success' },\n          { migrationName: 'migration1', direction: 'Down', status: 'Success' },\n        ])\n\n        expect(executedUpMethods).to.eql([\n          'migration1',\n          'migration2',\n          'migration3',\n        ])\n        expect(executedDownMethods).to.eql([\n          'migration3',\n          'migration2',\n          'migration1',\n        ])\n      })\n\n      it('should migrate down to a specific migration', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration3',\n          'migration4',\n        ])\n\n        const { results: results1 } = await migrator1.migrateTo('migration4')\n\n        const [migrator2, executedUpMethods2, executedDownMethods2] =\n          createMigrations([\n            'migration1',\n            'migration2',\n            'migration3',\n            'migration4',\n          ])\n\n        const { results: results2 } = await migrator2.migrateTo('migration2')\n\n        expect(results1).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration4', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(results2).to.eql([\n          { migrationName: 'migration4', direction: 'Down', status: 'Success' },\n          { migrationName: 'migration3', direction: 'Down', status: 'Success' },\n        ])\n\n        expect(executedUpMethods1).to.eql([\n          'migration1',\n          'migration2',\n          'migration3',\n          'migration4',\n        ])\n\n        expect(executedUpMethods2).to.eql([])\n        expect(executedDownMethods2).to.eql(['migration4', 'migration3'])\n      })\n\n      describe('with allowUnorderedMigrations enabled', () => {\n        it('should migrate up to a specific migration', async () => {\n          const [migrator1, executedUpMethods1] = createMigrations(\n            ['migration1', 'migration3', 'migration4', 'migration5'],\n            { allowUnorderedMigrations: true },\n          )\n\n          const { results: results1 } = await migrator1.migrateTo('migration3')\n\n          const [migrator2, executedUpMethods2] = createMigrations(\n            [\n              'migration1',\n              'migration2',\n              'migration3',\n              'migration4',\n              'migration5',\n            ],\n            { allowUnorderedMigrations: true },\n          )\n\n          const { results: results2 } = await migrator2.migrateTo('migration4')\n\n          expect(results1).to.eql([\n            { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n            { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n          ])\n\n          expect(results2).to.eql([\n            { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n            { migrationName: 'migration4', direction: 'Up', status: 'Success' },\n          ])\n\n          expect(executedUpMethods1).to.eql(['migration1', 'migration3'])\n          expect(executedUpMethods2).to.eql(['migration2', 'migration4'])\n        })\n\n        it('should migrate all the way down', async () => {\n          const [migrator1, executedUpMethods1] = createMigrations(\n            ['migration1', 'migration2', 'migration4'],\n            { allowUnorderedMigrations: true },\n          )\n\n          const { results: results1 } = await migrator1.migrateToLatest()\n\n          const [migrator2, executedUpMethods2, executedDownMethods2] =\n            createMigrations(\n              ['migration1', 'migration2', 'migration3', 'migration4'],\n              { allowUnorderedMigrations: true },\n            )\n\n          const { results: results2 } = await migrator2.migrateTo(NO_MIGRATIONS)\n\n          expect(results1).to.eql([\n            { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n            { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n            { migrationName: 'migration4', direction: 'Up', status: 'Success' },\n          ])\n\n          expect(results2).to.eql([\n            {\n              migrationName: 'migration4',\n              direction: 'Down',\n              status: 'Success',\n            },\n            {\n              migrationName: 'migration2',\n              direction: 'Down',\n              status: 'Success',\n            },\n            {\n              migrationName: 'migration1',\n              direction: 'Down',\n              status: 'Success',\n            },\n          ])\n\n          expect(executedUpMethods1).to.eql([\n            'migration1',\n            'migration2',\n            'migration4',\n          ])\n          expect(executedUpMethods2).to.eql([])\n          expect(executedDownMethods2).to.eql([\n            'migration4',\n            'migration2',\n            'migration1',\n          ])\n        })\n\n        it('should migrate down to a specific migration', async () => {\n          const [migrator1, executedUpMethods1] = createMigrations(\n            ['migration1', 'migration2', 'migration3', 'migration5'],\n            { allowUnorderedMigrations: true },\n          )\n\n          const { results: results1 } = await migrator1.migrateTo('migration5')\n\n          const [migrator2, executedUpMethods2, executedDownMethods2] =\n            createMigrations(\n              [\n                'migration1',\n                'migration2',\n                'migration3',\n                'migration4',\n                'migration5',\n              ],\n              { allowUnorderedMigrations: true },\n            )\n\n          const { results: results2 } = await migrator2.migrateTo('migration2')\n\n          expect(results1).to.eql([\n            { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n            { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n            { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n            { migrationName: 'migration5', direction: 'Up', status: 'Success' },\n          ])\n\n          expect(results2).to.eql([\n            {\n              migrationName: 'migration5',\n              direction: 'Down',\n              status: 'Success',\n            },\n            {\n              migrationName: 'migration3',\n              direction: 'Down',\n              status: 'Success',\n            },\n          ])\n\n          expect(executedUpMethods1).to.eql([\n            'migration1',\n            'migration2',\n            'migration3',\n            'migration5',\n          ])\n\n          expect(executedUpMethods2).to.eql([])\n          expect(executedDownMethods2).to.eql(['migration5', 'migration3'])\n        })\n\n        it('should migrate down if allowUnorderedMigrations is enabled and migration names are not in order', async () => {\n          const [migrator1, executedUpMethods1] = createMigrations(\n            ['migration1', 'migration3'],\n            { allowUnorderedMigrations: true },\n          )\n\n          const { results: results1 } = await migrator1.migrateToLatest()\n\n          const [migrator2, executedUpMethods2] = createMigrations(\n            ['migration1', 'migration2', 'migration3'],\n            {\n              allowUnorderedMigrations: true,\n            },\n          )\n\n          const { results: results2 } = await migrator2.migrateToLatest()\n\n          expect(results1).to.eql([\n            { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n            { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n          ])\n\n          expect(results2).to.eql([\n            {\n              migrationName: 'migration2',\n              direction: 'Up',\n              status: 'Success',\n            },\n          ])\n\n          expect(executedUpMethods1).to.eql(['migration1', 'migration3'])\n          expect(executedUpMethods2).to.eql(['migration2'])\n\n          const [migrator3, executedUpMethods3, executedDownMethods3] =\n            createMigrations(['migration1', 'migration2', 'migration3'], {\n              allowUnorderedMigrations: true,\n            })\n\n          const { results: results3 } = await migrator3.migrateDown()\n          expect(results3).to.eql([\n            {\n              migrationName: 'migration2',\n              direction: 'Down',\n              status: 'Success',\n            },\n          ])\n\n          expect(executedUpMethods3).to.eql([])\n          expect(executedDownMethods3).to.eql(['migration2'])\n        })\n      })\n    })\n\n    describe('migrateUp', () => {\n      const sandbox = createSandbox()\n      let transactionSpy: SinonSpy<\n        Parameters<Kysely<Database>['transaction']>,\n        ReturnType<Kysely<Database>['transaction']>\n      >\n\n      beforeEach(() => {\n        transactionSpy = sandbox.spy(ctx.db, 'transaction')\n      })\n\n      afterEach(() => {\n        sandbox.restore()\n      })\n\n      it('should migrate up one step', async () => {\n        const [migrator, executedUpMethods] = createMigrations([\n          'migration1',\n          'migration2',\n        ])\n\n        const { results: results1 } = await migrator.migrateUp()\n\n        expect(results1).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(executedUpMethods).to.eql(['migration1'])\n\n        const { results: results2 } = await migrator.migrateUp()\n\n        expect(results2).to.eql([\n          { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(executedUpMethods).to.eql(['migration1', 'migration2'])\n\n        const { results: results3 } = await migrator.migrateUp()\n\n        expect(results3).to.eql([])\n        expect(executedUpMethods).to.eql(['migration1', 'migration2'])\n      })\n\n      it('should return an error when migrating up if a new migration is added before the last executed one', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations([\n          'migration1',\n          'migration3',\n        ])\n\n        await migrator1.migrateToLatest()\n\n        const [migrator2, executedUpMethods2] = createMigrations([\n          'migration1',\n          'migration2',\n          'migration3',\n          'migration4',\n        ])\n\n        const { error } = await migrator2.migrateUp()\n\n        expect(error).to.be.an.instanceOf(Error)\n        expect(getMessage(error)).to.eql(\n          'corrupted migrations: expected previously executed migration migration3 to be at index 1 but migration2 was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.',\n        )\n\n        expect(executedUpMethods1).to.eql(['migration1', 'migration3'])\n        expect(executedUpMethods2).to.eql([])\n      })\n\n      it('should migrate up one step with allowUnorderedMigrations enabled', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations(\n          ['migration1', 'migration3'],\n          { allowUnorderedMigrations: true },\n        )\n\n        const { results: results1 } = await migrator1.migrateToLatest()\n\n        const [migrator2, executedUpMethods2] = createMigrations(\n          ['migration1', 'migration2', 'migration3', 'migration4'],\n          { allowUnorderedMigrations: true },\n        )\n\n        const { results: results2 } = await migrator2.migrateUp()\n        const { results: results3 } = await migrator2.migrateUp()\n\n        expect(results1).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n          { migrationName: 'migration3', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(results2).to.eql([\n          { migrationName: 'migration2', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(results3).to.eql([\n          { migrationName: 'migration4', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(executedUpMethods1).to.eql(['migration1', 'migration3'])\n        expect(executedUpMethods2).to.eql(['migration2', 'migration4'])\n      })\n\n      it('should not execute in transaction if disableTransactions is true', async () => {\n        const [migrator, executedUpMethods] = createMigrations(['migration1'], {\n          disableTransactions: true,\n        })\n\n        const { results } = await migrator.migrateUp()\n\n        expect(results).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(executedUpMethods).to.eql(['migration1'])\n\n        expect(transactionSpy.called).to.be.false\n      })\n\n      it('should execute in transaction if disableTransactions is false and transactionDdl supported', async () => {\n        const [migrator, executedUpMethods] = createMigrations(['migration1'], {\n          disableTransactions: false,\n        })\n\n        const { results } = await migrator.migrateUp()\n\n        expect(results).to.eql([\n          { migrationName: 'migration1', direction: 'Up', status: 'Success' },\n        ])\n\n        expect(executedUpMethods).to.eql(['migration1'])\n\n        if (ctx.db.getExecutor().adapter.supportsTransactionalDdl) {\n          expect(transactionSpy.called).to.be.true\n        } else {\n          expect(transactionSpy.called).to.be.false\n        }\n      })\n    })\n\n    describe('migrateDown', () => {\n      it('should migrate down one step', async () => {\n        const [migrator, executedUpMethods, executedDownMethods] =\n          createMigrations([\n            'migration1',\n            'migration2',\n            'migration3',\n            'migration4',\n          ])\n\n        await migrator.migrateUp()\n        await migrator.migrateUp()\n\n        const { results: results1 } = await migrator.migrateDown()\n        const { results: results2 } = await migrator.migrateDown()\n        const { results: results3 } = await migrator.migrateDown()\n\n        expect(results1).to.eql([\n          { migrationName: 'migration2', direction: 'Down', status: 'Success' },\n        ])\n\n        expect(results2).to.eql([\n          { migrationName: 'migration1', direction: 'Down', status: 'Success' },\n        ])\n\n        expect(results3).to.eql([])\n\n        expect(executedUpMethods).to.eql(['migration1', 'migration2'])\n        expect(executedDownMethods).to.eql(['migration2', 'migration1'])\n      })\n\n      it('should return an error if a new migration is added before the last executed one', async () => {\n        const [migrator1, executedUpMethods1] = createMigrations([\n          'migration1',\n          'migration3',\n        ])\n\n        await migrator1.migrateToLatest()\n\n        const [migrator2, _executedUpMethods2, executedDownMethods2] =\n          createMigrations(['migration1', 'migration2', 'migration3'])\n\n        const { error } = await migrator2.migrateDown()\n\n        expect(error).to.be.an.instanceOf(Error)\n        expect(getMessage(error)).to.eql(\n          'corrupted migrations: expected previously executed migration migration3 to be at index 1 but migration2 was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.',\n        )\n\n        expect(executedUpMethods1).to.eql(['migration1', 'migration3'])\n        expect(executedDownMethods2).to.eql([])\n      })\n\n      it('should migrate down one step with allowUnorderedMigrations enabled', async () => {\n        const [migrator1, executedUpMethods1, _executedDownMethods1] =\n          createMigrations(['migration1', 'migration2', 'migration4'], {\n            allowUnorderedMigrations: true,\n          })\n\n        await migrator1.migrateToLatest()\n\n        const [migrator2, _executedUpMethods2, executedDownMethods2] =\n          createMigrations(\n            [\n              'migration1',\n              'migration2',\n              'migration3',\n              'migration4',\n              'migration5',\n            ],\n            { allowUnorderedMigrations: true },\n          )\n\n        const { results: results1 } = await migrator2.migrateDown()\n        const { results: results2 } = await migrator2.migrateDown()\n        const { results: results3 } = await migrator2.migrateDown()\n        const { results: results4 } = await migrator2.migrateDown()\n\n        expect(results1).to.eql([\n          { migrationName: 'migration4', direction: 'Down', status: 'Success' },\n        ])\n\n        expect(results2).to.eql([\n          { migrationName: 'migration2', direction: 'Down', status: 'Success' },\n        ])\n\n        expect(results3).to.eql([\n          { migrationName: 'migration1', direction: 'Down', status: 'Success' },\n        ])\n\n        expect(results4).to.eql([])\n\n        expect(executedUpMethods1).to.eql([\n          'migration1',\n          'migration2',\n          'migration4',\n        ])\n        expect(executedDownMethods2).to.eql([\n          'migration4',\n          'migration2',\n          'migration1',\n        ])\n      })\n\n      describe('Migrate up should work when timestamps are equal', () => {\n        let originalToIsoString: typeof Date.prototype.toISOString\n\n        before(() => {\n          originalToIsoString = Date.prototype.toISOString\n          const defaultDateIsoString = new Date(2024, 0, 11).toISOString()\n          Date.prototype.toISOString = () => defaultDateIsoString\n        })\n\n        after(() => {\n          Date.prototype.toISOString = originalToIsoString\n        })\n\n        it('should use the same ordering strategy for migrations for both not executed migrations and executed migrations', async () => {\n          const [migrator1, executedUpMethods1] = createMigrations([\n            '2024-01-01-create-table',\n            '2024-01-01.2-update-table',\n          ])\n\n          await migrator1.migrateToLatest()\n\n          const [migrator2, executedUpMethods2] = createMigrations([\n            '2024-01-01-create-table',\n            '2024-01-01.2-update-table',\n          ])\n\n          const { results: results2, error } = await migrator2.migrateToLatest()\n          expect(error).to.be.undefined\n          expect(results2).to.eql([])\n\n          expect(executedUpMethods1).to.eql([\n            '2024-01-01-create-table',\n            '2024-01-01.2-update-table',\n          ])\n          expect(executedUpMethods2).to.eql([])\n        })\n      })\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      describe('custom migration tables in a custom schema', () => {\n        it('should create custom migration tables in custom schema', async () => {\n          const [migrator, executedUpMethods] = createMigrations(\n            ['migration1', 'migration2', 'migration3', 'migration4'],\n            {\n              migrationTableName: CUSTOM_MIGRATION_TABLE,\n              migrationLockTableName: CUSTOM_MIGRATION_LOCK_TABLE,\n              migrationTableSchema: CUSTOM_MIGRATION_SCHEMA,\n            },\n          )\n\n          let promises: Promise<MigrationResultSet>[] = []\n          // Run the migration 20 times in parallel to make sure the schema\n          // related code can be run in parallel.\n          for (let i = 0; i < 20; ++i) {\n            promises.push(migrator.migrateTo('migration2'))\n          }\n          const results = await Promise.all(promises)\n          for (const result of results) {\n            expect(result.error).to.equal(undefined)\n          }\n\n          expect(executedUpMethods).to.eql(['migration1', 'migration2'])\n\n          expect(\n            await doesTableExists(\n              CUSTOM_MIGRATION_LOCK_TABLE,\n              CUSTOM_MIGRATION_SCHEMA,\n            ),\n          ).to.equal(true)\n\n          expect(\n            await doesTableExists(\n              CUSTOM_MIGRATION_LOCK_TABLE,\n              CUSTOM_MIGRATION_SCHEMA,\n            ),\n          ).to.equal(true)\n\n          expect(await doesTableExists(DEFAULT_MIGRATION_TABLE)).to.equal(false)\n          expect(await doesTableExists(DEFAULT_MIGRATION_LOCK_TABLE)).to.equal(\n            false,\n          )\n        })\n      })\n    }\n\n    async function deleteMigrationTables(): Promise<void> {\n      if (dialect !== 'sqlite') {\n        await ctx.db.schema\n          .withSchema(CUSTOM_MIGRATION_SCHEMA)\n          .dropTable(CUSTOM_MIGRATION_TABLE)\n          .ifExists()\n          .execute()\n\n        await ctx.db.schema\n          .withSchema(CUSTOM_MIGRATION_SCHEMA)\n          .dropTable(CUSTOM_MIGRATION_LOCK_TABLE)\n          .ifExists()\n          .execute()\n\n        await ctx.db.schema\n          .dropSchema(CUSTOM_MIGRATION_SCHEMA)\n          .ifExists()\n          .execute()\n      }\n\n      await ctx.db.schema\n        .dropTable(DEFAULT_MIGRATION_TABLE)\n        .ifExists()\n        .execute()\n\n      await ctx.db.schema\n        .dropTable(DEFAULT_MIGRATION_LOCK_TABLE)\n        .ifExists()\n        .execute()\n    }\n\n    function createMigrations(\n      migrationConfigs: (string | { name: string; error?: string })[],\n      migratorConfig?: Partial<MigratorProps>,\n    ): [Migrator, string[], string[]] {\n      const executedUpMethods: string[] = []\n      const executedDownMethods: string[] = []\n\n      const migrations = migrationConfigs.reduce<Record<string, Migration>>(\n        (migrations, rawConfig) => {\n          const config =\n            typeof rawConfig === 'string' ? { name: rawConfig } : rawConfig\n\n          return {\n            ...migrations,\n            [config.name]: {\n              async up(_db): Promise<void> {\n                await sleep(20)\n\n                if (config.error) {\n                  throw new Error(config.error)\n                }\n\n                executedUpMethods.push(config.name)\n              },\n\n              async down(_db): Promise<void> {\n                await sleep(20)\n\n                if (config.error) {\n                  throw new Error(config.error)\n                }\n\n                executedDownMethods.push(config.name)\n              },\n            },\n          }\n        },\n        {},\n      )\n\n      return [\n        new Migrator({\n          db: ctx.db,\n          provider: {\n            getMigrations: () => Promise.resolve(migrations),\n          },\n          ...migratorConfig,\n        }),\n        executedUpMethods,\n        executedDownMethods,\n      ]\n    }\n\n    async function doesTableExists(\n      tableName: string,\n      schema?: string,\n    ): Promise<boolean> {\n      const tables = await ctx.db.introspection.getTables()\n      return !!tables.find(\n        (it) => it.name === tableName && (!schema || it.schema === schema),\n      )\n    }\n\n    function sleep(millis: number): Promise<void> {\n      return new Promise((resolve) => setTimeout(resolve, millis))\n    }\n  })\n}\n\nfunction getMessage(obj: unknown): string | undefined {\n  if (isObject(obj) && typeof obj.message === 'string') {\n    return obj.message\n  }\n}\n\nfunction isObject(obj: unknown): obj is Record<string, unknown> {\n  return typeof obj === 'object' && obj !== null\n}\n"
  },
  {
    "path": "test/node/src/object-util.test.ts",
    "content": "import { isPlainObject } from '../../../dist/cjs/util/object-utils'\n\nimport { expect } from './test-setup.js'\n\ndescribe('object util', () => {\n  it('isPlainObject', async () => {\n    class SomeClass {}\n\n    for (const obj of [{ foo: 'bar' }, Object.create(null)]) {\n      expect(isPlainObject(obj)).to.equal(true)\n    }\n\n    for (const obj of [\n      [],\n      new Date(),\n      Buffer.allocUnsafe(10),\n      new ArrayBuffer(10),\n      new Int32Array(10),\n      new Float64Array(10),\n      '',\n      42,\n      false,\n      null,\n      undefined,\n      new SomeClass(),\n    ]) {\n      expect(isPlainObject(obj)).to.equal(false)\n    }\n  })\n})\n"
  },
  {
    "path": "test/node/src/order-by.test.ts",
    "content": "import { sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  NOT_SUPPORTED,\n  insertDefaultDataSet,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: order by`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should order by one column', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .orderBy('first_name')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" order by \"first_name\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select * from `person` order by `first_name`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select * from \"person\" order by \"first_name\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" order by \"first_name\"',\n          parameters: [],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(3)\n      expect(persons.map((it) => it.first_name)).to.eql([\n        'Arnold',\n        'Jennifer',\n        'Sylvester',\n      ])\n    })\n\n    it('should order by two columns in two invocations', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .orderBy('first_name')\n        .orderBy('last_name', 'desc')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" order by \"first_name\", \"last_name\" desc',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select * from `person` order by `first_name`, `last_name` desc',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select * from \"person\" order by \"first_name\", \"last_name\" desc',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" order by \"first_name\", \"last_name\" desc',\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should order by two columns in one invocations', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .orderBy(['first_name', 'last_name desc'])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" order by \"first_name\", \"last_name\" desc',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select * from `person` order by `first_name`, `last_name` desc',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select * from \"person\" order by \"first_name\", \"last_name\" desc',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" order by \"first_name\", \"last_name\" desc',\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should order by aliased columns', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select([\n          'first_name as fn',\n          'middle_name as mn',\n          'last_name as ln',\n          'gender as g',\n        ])\n        .orderBy('fn')\n        .orderBy('mn asc')\n        .orderBy(['ln desc', 'g'])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            'select \"first_name\" as \"fn\",',\n            '\"middle_name\" as \"mn\",',\n            '\"last_name\" as \"ln\",',\n            '\"gender\" as \"g\"',\n            'from \"person\" order by \"fn\", \"mn\" asc, \"ln\" desc, \"g\"',\n          ],\n          parameters: [],\n        },\n        mysql: {\n          sql: [\n            'select `first_name` as `fn`,',\n            '`middle_name` as `mn`,',\n            '`last_name` as `ln`,',\n            '`gender` as `g`',\n            'from `person` order by `fn`, `mn` asc, `ln` desc, `g`',\n          ],\n          parameters: [],\n        },\n        mssql: {\n          sql: [\n            'select \"first_name\" as \"fn\",',\n            '\"middle_name\" as \"mn\",',\n            '\"last_name\" as \"ln\",',\n            '\"gender\" as \"g\"',\n            'from \"person\" order by \"fn\", \"mn\" asc, \"ln\" desc, \"g\"',\n          ],\n          parameters: [],\n        },\n        sqlite: {\n          sql: [\n            'select \"first_name\" as \"fn\",',\n            '\"middle_name\" as \"mn\",',\n            '\"last_name\" as \"ln\",',\n            '\"gender\" as \"g\"',\n            'from \"person\" order by \"fn\", \"mn\" asc, \"ln\" desc, \"g\"',\n          ],\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should order by expressions', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .orderBy(sql`coalesce(${sql.ref('first_name')}, ${sql.lit('foo')}) asc`)\n        .orderBy((eb) => eb.fn.coalesce('last_name', sql.lit('foo')))\n        .orderBy([\n          sql`coalesce(${sql.ref('gender')}, ${sql.lit('foo')})`,\n          (eb) => sql`${eb.fn.coalesce('middle_name', sql.lit('foo'))} desc`,\n        ])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: [\n            'select * from \"person\"',\n            `order by coalesce(\"first_name\", 'foo') asc,`,\n            `coalesce(\"last_name\", 'foo'),`,\n            `coalesce(\"gender\", 'foo'),`,\n            `coalesce(\"middle_name\", 'foo') desc`,\n          ],\n          parameters: [],\n        },\n        mysql: {\n          sql: [\n            'select * from `person`',\n            \"order by coalesce(`first_name`, 'foo') asc,\",\n            \"coalesce(`last_name`, 'foo'),\",\n            \"coalesce(`gender`, 'foo'),\",\n            \"coalesce(`middle_name`, 'foo') desc\",\n          ],\n          parameters: [],\n        },\n        mssql: {\n          sql: [\n            'select * from \"person\"',\n            `order by coalesce(\"first_name\", 'foo') asc,`,\n            `coalesce(\"last_name\", 'foo'),`,\n            `coalesce(\"gender\", 'foo'),`,\n            `coalesce(\"middle_name\", 'foo') desc`,\n          ],\n          parameters: [],\n        },\n        sqlite: {\n          sql: [\n            'select * from \"person\"',\n            `order by coalesce(\"first_name\", 'foo') asc,`,\n            `coalesce(\"last_name\", 'foo'),`,\n            `coalesce(\"gender\", 'foo'),`,\n            `coalesce(\"middle_name\", 'foo') desc`,\n          ],\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('order by raw expression and a direction', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .orderBy((eb) => eb.fn.coalesce('first_name', sql.lit('foo')), 'asc')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select * from \"person\" order by coalesce(\"first_name\", 'foo') asc`,\n          parameters: [],\n        },\n        mysql: {\n          sql: \"select * from `person` order by coalesce(`first_name`, 'foo') asc\",\n          parameters: [],\n        },\n        mssql: {\n          sql: `select * from \"person\" order by coalesce(\"first_name\", 'foo') asc`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: `select * from \"person\" order by coalesce(\"first_name\", 'foo') asc`,\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('order by a direction via builder', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .orderBy('last_name', (ob) => ob.desc())\n        .orderBy('first_name', (ob) => ob.asc())\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" order by \"last_name\" desc, \"first_name\" asc',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select * from `person` order by `last_name` desc, `first_name` asc',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select * from \"person\" order by \"last_name\" desc, \"first_name\" asc',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" order by \"last_name\" desc, \"first_name\" asc',\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres' || dialect === 'sqlite') {\n      it('order by nulls first', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .orderBy('last_name', (ob) => ob.desc().nullsFirst())\n          .orderBy('first_name', (ob) => ob.nullsFirst())\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" order by \"last_name\" desc nulls first, \"first_name\" nulls first',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'select * from \"person\" order by \"last_name\" desc nulls first, \"first_name\" nulls first',\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it('order by nulls last', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .orderBy('last_name', (ob) => ob.desc().nullsLast())\n          .orderBy('first_name', (ob) => ob.nullsLast())\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" order by \"last_name\" desc nulls last, \"first_name\" nulls last',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'select * from \"person\" order by \"last_name\" desc nulls last, \"first_name\" nulls last',\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n    }\n\n    it('order by collate', async () => {\n      const collation = {\n        postgres: 'pg_c_utf8',\n        mysql: 'utf8mb4_general_ci',\n        mssql: 'Latin1_General_CI_AS',\n        sqlite: 'nocase',\n      }[dialect]\n\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .orderBy('last_name', (ob) => ob.collate(collation).desc())\n        .orderBy('first_name', (ob) => ob.collate(collation))\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" order by \"last_name\" collate \"pg_c_utf8\" desc, \"first_name\" collate \"pg_c_utf8\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select * from `person` order by `last_name` collate `utf8mb4_general_ci` desc, `first_name` collate `utf8mb4_general_ci`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select * from \"person\" order by \"last_name\" collate Latin1_General_CI_AS desc, \"first_name\" collate Latin1_General_CI_AS',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" order by \"last_name\" collate \"nocase\" desc, \"first_name\" collate \"nocase\"',\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres') {\n      it('order by raw expression in direction', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .orderBy('person.first_name', sql`nulls last`)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" order by \"person\".\"first_name\" nulls last',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/parse-json-results-plugin.test.ts",
    "content": "import { ParseJSONResultsPlugin } from '../../..'\nimport { createQueryId } from '../../../dist/cjs/util/query-id.js'\n\ndescribe('ParseJSONResultsPlugin', () => {\n  describe(\"when `objectStrategy` is 'create'\", () => {\n    let plugin: ParseJSONResultsPlugin\n\n    beforeEach(() => {\n      plugin = new ParseJSONResultsPlugin({ objectStrategy: 'create' })\n    })\n\n    it('should parse JSON results that contain readonly arrays/objects', async () => {\n      await plugin.transformResult({\n        queryId: createQueryId(),\n        result: {\n          rows: [\n            Object.freeze({\n              id: 1,\n              carIds: Object.freeze([1, 2, 3]),\n              metadata: JSON.stringify({ foo: 'bar' }),\n            }),\n          ],\n        },\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/node/src/performance.test.ts",
    "content": "import { sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  insertDefaultDataSet,\n  DIALECTS,\n} from './test-setup.js'\n\nif (DIALECTS.includes('postgres')) {\n  describe.skip(`query builder performance`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, 'postgres')\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('simple query builder performance test', async () => {\n      function test() {\n        ctx.db\n          .selectFrom(['person as p', 'pet'])\n          .innerJoin('toy', 'toy.pet_id', 'pet.id')\n          .whereRef('p.id', '=', 'pet.owner_id')\n          .where('toy.id', '=', 1)\n          .where('p.id', 'in', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n          .where(({ exists, selectFrom }) =>\n            exists(\n              selectFrom('toy_schema.toy').whereRef(\n                'toy_schema.toy.id',\n                '=',\n                'toy.id',\n              ),\n            ),\n          )\n          .select([\n            'toy.price as price',\n            sql`concat(${sql.ref('first_name')}, ' ', ${sql.ref(\n              'last_name',\n            )})`.as('full_name'),\n          ])\n          .compile()\n      }\n\n      const WARMUP_ROUNDS = 1000\n      const TEST_ROUNDS = 100000\n\n      for (let i = 0; i < WARMUP_ROUNDS; ++i) {\n        test()\n      }\n\n      const t0 = new Date()\n      for (let i = 0; i < TEST_ROUNDS; ++i) {\n        test()\n      }\n      const t1 = new Date()\n\n      console.log(\n        'query building time:',\n        (t1.getTime() - t0.getTime()) / TEST_ROUNDS,\n        'ms',\n      )\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/query-id.test.ts",
    "content": "import { expect } from 'chai'\nimport {\n  DatabaseConnection,\n  DummyDriver,\n  Kysely,\n  PostgresAdapter,\n  PostgresIntrospector,\n  PostgresQueryCompiler,\n  RootOperationNode,\n  QueryId,\n} from '../../..'\nimport { Database } from './test-setup'\n\ndescribe('queryId', () => {\n  const visits = new Map()\n\n  const db = new Kysely<Database>({\n    dialect: {\n      createAdapter: () => new PostgresAdapter(),\n      createDriver: () =>\n        new (class extends DummyDriver {\n          async acquireConnection(): Promise<DatabaseConnection> {\n            // @ts-ignore\n            return {\n              executeQuery: async ({ queryId }) => {\n                checkIn(queryId, 'connection.executeQuery')\n\n                return {\n                  rows: [],\n                }\n              },\n            }\n          }\n        })(),\n      createIntrospector: (db) => new PostgresIntrospector(db),\n      createQueryCompiler: () =>\n        new (class SomeCompiler extends PostgresQueryCompiler {\n          compileQuery(node: RootOperationNode, queryId: QueryId) {\n            checkIn(queryId, 'compiler.compileQuery')\n\n            return super.compileQuery(node, queryId)\n          }\n        })(),\n    },\n    plugins: [\n      {\n        transformQuery: (args) => {\n          checkIn(args.queryId, 'plugin.transformQuery')\n\n          return args.node\n        },\n        transformResult: async (args) => {\n          checkIn(args.queryId, 'plugin.transformResult')\n\n          return args.result\n        },\n      },\n    ],\n  })\n\n  it('should pass query id around, allowing async communication between compilers, plugins and connections', async () => {\n    await db.selectFrom('person').where('id', '=', 1).execute()\n\n    expect(Array.from(visits.values())[0]).to.deep.equal([\n      'plugin.transformQuery',\n      'compiler.compileQuery',\n      'connection.executeQuery',\n      'plugin.transformResult',\n    ])\n  })\n\n  function checkIn(queryId: QueryId, place: string): void {\n    visits.set(queryId, [...(visits.get(queryId) || []), place])\n  }\n})\n"
  },
  {
    "path": "test/node/src/raw-query.test.ts",
    "content": "import { sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  expect,\n  insertDefaultDataSet,\n  testSql,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: raw queries`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should run a raw select query', async () => {\n      const gender = 'male'\n\n      const result = await sql<{\n        first_name: string\n      }>`select first_name from person where gender = ${gender} order by first_name asc, last_name asc`.execute(\n        ctx.db,\n      )\n\n      expect(result.insertId).to.equal(undefined)\n      expect(result.numAffectedRows).to.equal(\n        dialect === 'mssql' ? 2n : undefined,\n      )\n      expect(result.rows).to.eql([\n        { first_name: 'Arnold' },\n        { first_name: 'Sylvester' },\n      ])\n    })\n\n    it('should run a raw update query', async () => {\n      const newFirstName = 'Updated'\n      const gender = 'male'\n\n      const result =\n        await sql`update person set first_name = ${newFirstName} where gender = ${gender}`.execute(\n          ctx.db,\n        )\n\n      expect(result.numAffectedRows).to.equal(2n)\n      expect(result.rows).to.eql([])\n    })\n\n    it('should run a raw delete query', async () => {\n      const gender = 'male'\n\n      const result =\n        await sql`delete from person where gender = ${gender}`.execute(ctx.db)\n\n      expect(result.numAffectedRows).to.equal(2n)\n      expect(result.rows).to.eql([])\n    })\n\n    if (dialect === 'postgres' || dialect === 'sqlite') {\n      it('should run a raw insert query', async () => {\n        const firstName = 'New'\n        const lastName = 'Personsson'\n        const gender = 'other'\n\n        const result =\n          await sql`insert into person (first_name, last_name, gender) values (${firstName}, ${lastName}, ${gender}) returning first_name, last_name`.execute(\n            ctx.db,\n          )\n\n        expect(result.insertId).to.equal(undefined)\n        expect(result.rows).to.eql([\n          { first_name: 'New', last_name: 'Personsson' },\n        ])\n      })\n    }\n\n    if (dialect === 'mysql') {\n      it('should run a raw insert query', async () => {\n        const firstName = 'New'\n        const lastName = 'Personsson'\n        const gender = 'other'\n\n        const result =\n          await sql`insert into person (first_name, last_name, gender) values (${firstName}, ${lastName}, ${gender})`.execute(\n            ctx.db,\n          )\n\n        expect(result.insertId! > 0n).to.be.equal(true)\n        expect(result.rows).to.eql([])\n      })\n    }\n\n    it('should compile a raw select query', async () => {\n      const gender = 'male'\n\n      const query = sql`select first_name from person where gender = ${gender} order by first_name asc, last_name asc`\n\n      testSql({ compile: () => query.compile(ctx.db) }, dialect, {\n        postgres: {\n          sql: 'select first_name from person where gender = $1 order by first_name asc, last_name asc',\n          parameters: [gender],\n        },\n        mysql: {\n          sql: 'select first_name from person where gender = ? order by first_name asc, last_name asc',\n          parameters: [gender],\n        },\n        mssql: {\n          sql: 'select first_name from person where gender = @1 order by first_name asc, last_name asc',\n          parameters: [gender],\n        },\n        sqlite: {\n          sql: 'select first_name from person where gender = ? order by first_name asc, last_name asc',\n          parameters: [gender],\n        },\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/raw-sql.test.ts",
    "content": "import {\n  sql,\n  CompiledQuery,\n  DefaultQueryCompiler,\n  createQueryId,\n} from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  insertDefaultDataSet,\n  testSql,\n  NOT_SUPPORTED,\n  expect,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: raw sql`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('substitutions should be interpreted as parameters by default', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .where(sql<boolean>`first_name between ${'A'} and ${'B'}`)\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" where first_name between $1 and $2',\n          parameters: ['A', 'B'],\n        },\n        mysql: {\n          sql: 'select * from `person` where first_name between ? and ?',\n          parameters: ['A', 'B'],\n        },\n        mssql: {\n          sql: 'select * from \"person\" where first_name between @1 and @2',\n          parameters: ['A', 'B'],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" where first_name between ? and ?',\n          parameters: ['A', 'B'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('substitutions should accept queries', async () => {\n      const compiler = new DefaultQueryCompiler()\n\n      let node = sql`before ${ctx.db\n        .selectFrom('person')\n        .selectAll()} after`.toOperationNode()\n      expect(compiler.compileQuery(node, createQueryId()).sql).to.equal(\n        `before (select * from \"person\") after`,\n      )\n\n      node = sql`before ${ctx.db.insertInto('person').values({\n        first_name: 'Jennifer',\n        last_name: 'Aniston',\n        gender: 'female',\n      })} after`.toOperationNode()\n      expect(compiler.compileQuery(node, createQueryId()).sql).to.equal(\n        `before insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3) after`,\n      )\n\n      node = sql`before ${ctx.db\n        .deleteFrom('person')\n        .where('id', '=', 1)} after`.toOperationNode()\n      expect(compiler.compileQuery(node, createQueryId()).sql).to.equal(\n        `before delete from \"person\" where \"id\" = $1 after`,\n      )\n\n      node = sql`before ${ctx.db\n        .updateTable('person')\n        .set('first_name', 'Jennifer')} after`.toOperationNode()\n      expect(compiler.compileQuery(node, createQueryId()).sql).to.equal(\n        `before update \"person\" set \"first_name\" = $1 after`,\n      )\n    })\n\n    it('sql.lit should turn substitutions from parameters into literal values', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .where(\n          sql<boolean>`first_name between ${sql.lit('A')} and ${sql.lit('B')}`,\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select * from \"person\" where first_name between 'A' and 'B'`,\n          parameters: [],\n        },\n        mysql: {\n          sql: \"select * from `person` where first_name between 'A' and 'B'\",\n          parameters: [],\n        },\n        mssql: {\n          sql: `select * from \"person\" where first_name between 'A' and 'B'`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: `select * from \"person\" where first_name between 'A' and 'B'`,\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('sql.id should turn substitutions from parameters into identifiers', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .where(sql<boolean>`${sql.id('first_name')} between ${'A'} and ${'B'}`)\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" where \"first_name\" between $1 and $2',\n          parameters: ['A', 'B'],\n        },\n        mysql: {\n          sql: 'select * from `person` where `first_name` between ? and ?',\n          parameters: ['A', 'B'],\n        },\n        mssql: {\n          sql: 'select * from \"person\" where \"first_name\" between @1 and @2',\n          parameters: ['A', 'B'],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" where \"first_name\" between ? and ?',\n          parameters: ['A', 'B'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      it('sql.id should separate multiple arguments by dots', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(\n            sql<boolean>`${sql.id(\n              dialect === 'postgres' ? 'public' : 'dbo',\n              'person',\n              'first_name',\n            )} between ${'A'} and ${'B'}`,\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"public\".\"person\".\"first_name\" between $1 and $2',\n            parameters: ['A', 'B'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select * from \"person\" where \"dbo\".\"person\".\"first_name\" between @1 and @2',\n            parameters: ['A', 'B'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    it('sql.ref should turn substitutions from parameters into column references', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .where(sql<boolean>`${sql.ref('first_name')} between ${'A'} and ${'B'}`)\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" where \"first_name\" between $1 and $2',\n          parameters: ['A', 'B'],\n        },\n        mysql: {\n          sql: 'select * from `person` where `first_name` between ? and ?',\n          parameters: ['A', 'B'],\n        },\n        mssql: {\n          sql: 'select * from \"person\" where \"first_name\" between @1 and @2',\n          parameters: ['A', 'B'],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" where \"first_name\" between ? and ?',\n          parameters: ['A', 'B'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      it('sql.ref should support schemas and table names', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(\n            sql<boolean>`${sql.ref(\n              `${dialect === 'postgres' ? 'public' : 'dbo'}.person.first_name`,\n            )} between ${'A'} and ${'B'}`,\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"public\".\"person\".\"first_name\" between $1 and $2',\n            parameters: ['A', 'B'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select * from \"person\" where \"dbo\".\"person\".\"first_name\" between @1 and @2',\n            parameters: ['A', 'B'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    it('sql.table should turn substitutions from parameters into table references', async () => {\n      const query = ctx.db\n        .selectFrom(sql`${sql.table('person')}`.as('person'))\n        .selectAll()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" as \"person\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select * from `person` as `person`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select * from \"person\" as \"person\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" as \"person\"',\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      it('sql.table should support schemas', async () => {\n        const query = ctx.db\n          .selectFrom(\n            sql`${sql.table(\n              `${dialect === 'postgres' ? 'public' : 'dbo'}.person`,\n            )}`.as('person'),\n          )\n          .selectAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"public\".\"person\" as \"person\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select * from \"dbo\".\"person\" as \"person\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    it('sql.join should turn substitutions from parameters into lists of things', async () => {\n      const names = ['Jennifer', 'Arnold']\n\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .where(sql<boolean>`first_name in (${sql.join(names)})`)\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" where first_name in ($1, $2)',\n          parameters: names,\n        },\n        mysql: {\n          sql: 'select * from `person` where first_name in (?, ?)',\n          parameters: names,\n        },\n        mssql: {\n          sql: 'select * from \"person\" where first_name in (@1, @2)',\n          parameters: names,\n        },\n        sqlite: {\n          sql: 'select * from \"person\" where first_name in (?, ?)',\n          parameters: names,\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres') {\n      it('second argument of sql.join should specify the separator', async () => {\n        const names = ['Jennifer', 'Arnold', 'Sylvester']\n\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(\n            sql<boolean>`first_name in (${sql.join(names, sql`::varchar,`)})`,\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where first_name in ($1::varchar,$2::varchar,$3)',\n            parameters: names,\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('CompiledQuery should support raw query with parameters', async () => {\n        const query = CompiledQuery.raw(\n          'select * from \"person\" where \"public\".\"person\".\"first_name\" between $1 and $2',\n          ['A', 'B'],\n        )\n        expect(query.sql).to.equal(\n          'select * from \"person\" where \"public\".\"person\".\"first_name\" between $1 and $2',\n        )\n        expect(query.parameters).to.deep.equal(['A', 'B'])\n        await ctx.db.executeQuery(query)\n      })\n    }\n\n    it('raw sql kitchen sink', async () => {\n      const result = await sql`insert into ${sql.table('toy')} (${sql.join([\n        sql.ref('name'),\n        sql.ref('pet_id'),\n        sql.ref('price'),\n      ])}) select ${sql.join([\n        sql.lit('Wheel').as('name'),\n        sql.ref('id'),\n        sql.lit(9.99).as('price'),\n      ])} from ${sql.table('pet')} where ${sql.ref(\n        'name',\n      )} = ${'Hammo'}`.execute(ctx.db)\n\n      const wheel = await ctx.db\n        .selectFrom('toy')\n        .where('name', '=', 'Wheel')\n        .selectAll()\n        .executeTakeFirstOrThrow()\n\n      expect(wheel.name).to.equal('Wheel')\n      expect(wheel.pet_id).to.be.a('number')\n      expect(wheel.price).to.equal(9.99)\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/replace.test.ts",
    "content": "import { InsertResult, Kysely, sql } from '../../../'\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  Person,\n  Database,\n  NOT_SUPPORTED,\n  insertDefaultDataSet,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  if (dialect === 'mysql' || dialect === 'sqlite') {\n    describe(`${dialect}: replace into`, () => {\n      let ctx: TestContext\n\n      before(async function () {\n        ctx = await initTest(this, dialect)\n      })\n\n      beforeEach(async () => {\n        await insertDefaultDataSet(ctx)\n      })\n\n      afterEach(async () => {\n        await clearDatabase(ctx)\n      })\n\n      after(async () => {\n        await destroyTest(ctx)\n      })\n\n      it('should insert one row', async () => {\n        const query = ctx.db.replaceInto('person').values({\n          id: 15,\n          first_name: 'Foo',\n          last_name: 'Barson',\n          gender: 'other',\n        })\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: 'replace into `person` (`id`, `first_name`, `last_name`, `gender`) values (?, ?, ?, ?)',\n            parameters: [15, 'Foo', 'Barson', 'other'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'replace into \"person\" (\"id\", \"first_name\", \"last_name\", \"gender\") values (?, ?, ?, ?)',\n            parameters: [15, 'Foo', 'Barson', 'other'],\n          },\n        })\n\n        const result = await query.executeTakeFirst()\n        expect(result).to.be.instanceOf(InsertResult)\n        expect(result.insertId).to.be.a('bigint')\n\n        expect(await getNewestPerson(ctx.db)).to.eql({\n          first_name: 'Foo',\n          last_name: 'Barson',\n        })\n      })\n\n      it('should insert one row with complex values', async () => {\n        const query = ctx.db.replaceInto('person').values({\n          id: 2500,\n          first_name: ctx.db\n            .selectFrom('pet')\n            .select(sql<string>`max(name)`.as('max_name')),\n          last_name: sql`concat('Bar', 'son')`,\n          gender: 'other',\n        })\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: \"replace into `person` (`id`, `first_name`, `last_name`, `gender`) values (?, (select max(name) as `max_name` from `pet`), concat('Bar', 'son'), ?)\",\n            parameters: [2500, 'other'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: `replace into \"person\" (\"id\", \"first_name\", \"last_name\", \"gender\") values (?, (select max(name) as \"max_name\" from \"pet\"), concat('Bar', 'son'), ?)`,\n            parameters: [2500, 'other'],\n          },\n        })\n\n        const result = await query.executeTakeFirst()\n        expect(result).to.be.instanceOf(InsertResult)\n\n        expect(await getNewestPerson(ctx.db)).to.eql({\n          first_name: 'Hammo',\n          last_name: 'Barson',\n        })\n      })\n\n      it('should insert the result of a select query', async () => {\n        const query = ctx.db\n          .replaceInto('person')\n          .columns(['first_name', 'gender'])\n          .expression((eb) =>\n            eb.selectFrom('pet').select(['name', sql`${'other'}`.as('gender')]),\n          )\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: 'replace into `person` (`first_name`, `gender`) select `name`, ? as `gender` from `pet`',\n            parameters: ['other'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'replace into \"person\" (\"first_name\", \"gender\") select \"name\", ? as \"gender\" from \"pet\"',\n            parameters: ['other'],\n          },\n        })\n\n        await query.execute()\n\n        const persons = await ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .orderBy('first_name')\n          .execute()\n\n        expect(persons.map((it) => it.first_name)).to.eql([\n          'Arnold',\n          'Catto',\n          'Doggo',\n          'Hammo',\n          'Jennifer',\n          'Sylvester',\n        ])\n      })\n\n      it('undefined values should be ignored', async () => {\n        const query = ctx.db.replaceInto('person').values({\n          id: 12,\n          gender: 'male',\n          middle_name: undefined,\n        })\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: 'replace into `person` (`id`, `gender`) values (?, ?)',\n            parameters: [12, 'male'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'replace into \"person\" (\"id\", \"gender\") values (?, ?)',\n            parameters: [12, 'male'],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it('should replace on conflict', async () => {\n        const [existingPet] = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .limit(1)\n          .execute()\n\n        const query = ctx.db\n          .replaceInto('pet')\n          .values({ ...existingPet, species: 'hamster' })\n\n        testSql(query, dialect, {\n          mysql: {\n            sql: 'replace into `pet` (`id`, `name`, `owner_id`, `species`) values (?, ?, ?, ?)',\n            parameters: [\n              existingPet.id,\n              existingPet.name,\n              existingPet.owner_id,\n              'hamster',\n            ],\n          },\n          postgres: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'replace into \"pet\" (\"id\", \"name\", \"owner_id\", \"species\") values (?, ?, ?, ?)',\n            parameters: [\n              existingPet.id,\n              existingPet.name,\n              existingPet.owner_id,\n              'hamster',\n            ],\n          },\n        })\n\n        await query.execute()\n\n        const updatedPet = await ctx.db\n          .selectFrom('pet')\n          .selectAll()\n          .where('id', '=', existingPet.id)\n          .executeTakeFirstOrThrow()\n\n        expect(updatedPet).to.containSubset({\n          name: 'Catto',\n          species: 'hamster',\n        })\n      })\n    })\n\n    async function getNewestPerson(\n      db: Kysely<Database>,\n    ): Promise<Pick<Person, 'first_name' | 'last_name'> | undefined> {\n      return await db\n        .selectFrom('person')\n        .select(['first_name', 'last_name'])\n        .where(\n          'id',\n          '=',\n          db.selectFrom('person').select(sql<number>`max(id)`.as('max_id')),\n        )\n        .executeTakeFirst()\n    }\n  }\n}\n"
  },
  {
    "path": "test/node/src/sanitize-identifiers.test.ts",
    "content": "import { Updateable } from '../../../dist/cjs'\n\nimport {\n  destroyTest,\n  initTest,\n  TestContext,\n  Person,\n  testSql,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: sanitize identifiers`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should escape identifier quotes', async () => {\n      const obj: Record<string, unknown> = {\n        first_name: 'foo',\n        'last_name\"`': 'bar',\n      }\n\n      const person = obj as unknown as Updateable<Person>\n      const query = ctx.db.updateTable('person').set(person)\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'update \"person\" set \"first_name\" = $1, \"last_name\"\"`\" = $2',\n          parameters: ['foo', 'bar'],\n        },\n        mysql: {\n          sql: 'update `person` set `first_name` = ?, `last_name\"``` = ?',\n          parameters: ['foo', 'bar'],\n        },\n        mssql: {\n          sql: 'update \"person\" set \"first_name\" = @1, \"last_name\"\"`\" = @2',\n          parameters: ['foo', 'bar'],\n        },\n        sqlite: {\n          sql: 'update \"person\" set \"first_name\" = ?, \"last_name\"\"`\" = ?',\n          parameters: ['foo', 'bar'],\n        },\n      })\n    })\n\n    it('should escape multiple identifier quotes', async () => {\n      const obj: Record<string, unknown> = {\n        first_name: 'foo',\n        'last_name\"\"``': 'bar',\n      }\n\n      const person = obj as unknown as Updateable<Person>\n      const query = ctx.db.updateTable('person').set(person)\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'update \"person\" set \"first_name\" = $1, \"last_name\"\"\"\"``\" = $2',\n          parameters: ['foo', 'bar'],\n        },\n        mysql: {\n          sql: 'update `person` set `first_name` = ?, `last_name\"\"````` = ?',\n          parameters: ['foo', 'bar'],\n        },\n        mssql: {\n          sql: 'update \"person\" set \"first_name\" = @1, \"last_name\"\"\"\"``\" = @2',\n          parameters: ['foo', 'bar'],\n        },\n        sqlite: {\n          sql: 'update \"person\" set \"first_name\" = ?, \"last_name\"\"\"\"``\" = ?',\n          parameters: ['foo', 'bar'],\n        },\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/schema.test.ts",
    "content": "import { fail } from 'assert'\nimport { ColumnMetadata, sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  expect,\n  initTest,\n  NOT_SUPPORTED,\n  TestContext,\n  testSql,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: schema`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n      await dropTestTables()\n    })\n\n    afterEach(async () => {\n      await dropTestTables()\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    describe('create table', () => {\n      if (dialect === 'postgres') {\n        it('should create a table with all data types', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'serial', (col) => col.primaryKey())\n            .addColumn('b', 'integer', (col) =>\n              col\n                .references('test.a')\n                .onDelete('cascade')\n                .onUpdate('restrict')\n                .check(sql`b < a`),\n            )\n            .addColumn('c', 'varchar')\n            .addColumn('d', 'varchar(10)')\n            .addColumn('e', 'bigint', (col) => col.unique().notNull())\n            .addColumn('f', 'double precision')\n            .addColumn('g', 'real')\n            .addColumn('h', 'text')\n            .addColumn('i', sql`varchar(123)`)\n            .addColumn('j', 'numeric(6, 2)')\n            .addColumn('k', 'decimal(8, 4)')\n            .addColumn('l', 'boolean', (col) => col.notNull().defaultTo(false))\n            .addColumn('m', 'date')\n            .addColumn('n', 'timestamptz')\n            .addColumn('o', 'uuid', (col) =>\n              col.defaultTo(sql`gen_random_uuid()`),\n            )\n            .addColumn('p', 'int2')\n            .addColumn('q', 'int4')\n            .addColumn('r', 'int8')\n            .addColumn('s', 'double precision', (col) =>\n              col\n                .generatedAlwaysAs(sql`f + g`)\n                .stored()\n                .notNull(),\n            )\n            .addColumn('t', 'time(6)')\n            .addColumn('tz', 'timetz(6)')\n            .addColumn('u', 'timestamp(6)', (col) =>\n              col.notNull().defaultTo(sql`current_timestamp`),\n            )\n            .addColumn('v', 'timestamptz(6)')\n            .addColumn('w', 'char(4)')\n            .addColumn('x', 'char')\n            .addColumn('y', 'bytea')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: [\n                'create table \"test\"',\n                '(\"a\" serial primary key,',\n                '\"b\" integer references \"test\" (\"a\") on delete cascade on update restrict check (b < a),',\n                '\"c\" varchar,',\n                '\"d\" varchar(10),',\n                '\"e\" bigint not null unique,',\n                '\"f\" double precision,',\n                '\"g\" real,',\n                '\"h\" text,',\n                '\"i\" varchar(123),',\n                '\"j\" numeric(6, 2),',\n                '\"k\" decimal(8, 4),',\n                '\"l\" boolean default false not null,',\n                '\"m\" date,',\n                '\"n\" timestamptz,',\n                '\"o\" uuid default gen_random_uuid(),',\n                '\"p\" int2,',\n                '\"q\" int4,',\n                '\"r\" int8,',\n                '\"s\" double precision generated always as (f + g) stored not null,',\n                '\"t\" time(6),',\n                '\"tz\" timetz(6),',\n                '\"u\" timestamp(6) default current_timestamp not null,',\n                '\"v\" timestamptz(6),',\n                '\"w\" char(4),',\n                '\"x\" char,',\n                '\"y\" bytea)',\n              ],\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n\n          expect(await getColumnMeta('test.a')).to.eql({\n            comment: undefined,\n            dataType: 'int4',\n            dataTypeSchema: 'pg_catalog',\n            isAutoIncrementing: true,\n            isNullable: false,\n            hasDefaultValue: true,\n            name: 'a',\n          })\n\n          expect(await getColumnMeta('test.b')).to.eql({\n            comment: undefined,\n            dataType: 'int4',\n            dataTypeSchema: 'pg_catalog',\n            isAutoIncrementing: false,\n            isNullable: true,\n            hasDefaultValue: false,\n            name: 'b',\n          })\n\n          expect(await getColumnMeta('test.l')).to.eql({\n            comment: undefined,\n            dataType: 'bool',\n            dataTypeSchema: 'pg_catalog',\n            isAutoIncrementing: false,\n            isNullable: false,\n            hasDefaultValue: true,\n            name: 'l',\n          })\n        })\n\n        it('should create a table with \"unique nulls not distinct\" modifier for a column', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'varchar(10)', (builder) =>\n              builder.unique().nullsNotDistinct(),\n            )\n            .addColumn('b', 'varchar(20)')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" varchar(10) unique nulls not distinct, \"b\" varchar(20))',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a table with \"unique nulls not distinct\" and other modifiers', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer', (builder) =>\n              builder\n                .check(sql`a < 100`)\n                .nullsNotDistinct()\n                .unique()\n                .defaultTo(10),\n            )\n            .addColumn('b', 'varchar(20)')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" integer default 10 unique nulls not distinct check (a < 100), \"b\" varchar(20))',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      } else if (dialect === 'mysql') {\n        it('should create a table with all data types', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer', (col) =>\n              col.primaryKey().autoIncrement(),\n            )\n            .addColumn('b', 'integer', (col) =>\n              col.references('test.a').onDelete('cascade').onUpdate('set null'),\n            )\n            .addColumn('c', 'varchar(255)')\n            .addColumn('d', 'bigint', (col) =>\n              col.unsigned().unique().notNull(),\n            )\n            .addColumn('e', 'double precision')\n            .addColumn('f', 'real')\n            .addColumn('g', 'text')\n            .addColumn('h', sql`varchar(123)`)\n            .addColumn('i', 'numeric(6, 2)')\n            .addColumn('j', 'decimal(8, 4)')\n            .addColumn('k', 'boolean', (col) => col.notNull().defaultTo(false))\n            .addColumn('l', 'date')\n            .addColumn('m', 'time')\n            .addColumn('n', 'datetime')\n            .addColumn('o', 'timestamp')\n            .addColumn('p', 'double precision', (col) =>\n              col\n                .generatedAlwaysAs(sql`e + f`)\n                .stored()\n                .notNull(),\n            )\n            .addColumn('q', 'time(6)')\n            .addColumn('r', 'datetime(6)')\n            .addColumn('s', 'timestamp(6)', (col) =>\n              col.notNull().defaultTo(sql`current_timestamp(6)`),\n            )\n            .addColumn('t', 'char(4)')\n            .addColumn('u', 'char')\n            .addColumn('v', 'binary(16)')\n            .addColumn('w', 'varbinary(16)')\n\n          testSql(builder, dialect, {\n            mysql: {\n              sql: [\n                'create table `test`',\n                '(`a` integer primary key auto_increment,',\n                '`b` integer references `test` (`a`) on delete cascade on update set null,',\n                '`c` varchar(255),',\n                '`d` bigint unsigned not null unique,',\n                '`e` double precision,',\n                '`f` real,',\n                '`g` text,',\n                '`h` varchar(123),',\n                '`i` numeric(6, 2),',\n                '`j` decimal(8, 4),',\n                '`k` boolean default false not null,',\n                '`l` date,',\n                '`m` time,',\n                '`n` datetime,',\n                '`o` timestamp,',\n                '`p` double precision generated always as (e + f) stored not null,',\n                '`q` time(6),',\n                '`r` datetime(6),',\n                '`s` timestamp(6) default current_timestamp(6) not null,',\n                '`t` char(4),',\n                '`u` char,',\n                '`v` binary(16),',\n                '`w` varbinary(16))',\n              ],\n              parameters: [],\n            },\n            postgres: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n\n          expect(await getColumnMeta('test.a')).to.eql({\n            comment: undefined,\n            dataType: 'int',\n            isAutoIncrementing: true,\n            isNullable: false,\n            hasDefaultValue: false,\n            name: 'a',\n          })\n\n          expect(await getColumnMeta('test.b')).to.eql({\n            comment: undefined,\n            dataType: 'int',\n            isAutoIncrementing: false,\n            isNullable: true,\n            hasDefaultValue: false,\n            name: 'b',\n          })\n\n          expect(await getColumnMeta('test.k')).to.eql({\n            comment: undefined,\n            dataType: 'tinyint',\n            isAutoIncrementing: false,\n            isNullable: false,\n            hasDefaultValue: true,\n            name: 'k',\n          })\n        })\n      } else if (dialect === 'mssql') {\n        it('should create a table with all data types', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer', (col) =>\n              col.identity().notNull().primaryKey(),\n            )\n            .addColumn('b', 'integer', (col) =>\n              col\n                .references('test.a')\n                .onDelete('no action')\n                .onUpdate('no action')\n                .check(sql`b < 10`),\n            )\n            .addColumn('c', 'varchar')\n            .addColumn('d', 'varchar(10)')\n            .addColumn('e', 'bigint', (col) => col.unique().notNull())\n            .addColumn('f', 'double precision')\n            .addColumn('g', 'real')\n            .addColumn('h', 'text')\n            .addColumn('i', sql`varchar(123)`)\n            .addColumn('j', 'numeric(6, 2)')\n            .addColumn('k', 'decimal(8, 4)')\n            .addColumn('l', sql`bit`, (col) => col.notNull().defaultTo(0))\n            .addColumn('m', 'date')\n            .addColumn('n', 'datetime', (col) =>\n              col.defaultTo(sql`current_timestamp`),\n            )\n            .addColumn('o', sql`uniqueidentifier`, (col) =>\n              col.notNull().defaultTo(sql`newid()`),\n            )\n            .addColumn('p', sql`smallint`)\n            .addColumn('q', sql`int`)\n            .addColumn('r', 'double precision', (col) => col.notNull())\n            .addColumn('s', 'time(6)')\n            .addColumn('t', 'timestamp', (col) => col.notNull())\n            .addColumn('u', sql`datetime2`)\n            .addColumn('v', 'char(4)')\n            .addColumn('w', 'char')\n            .addColumn('x', 'binary')\n            .addColumn('y', sql``, (col) => col.modifyEnd(sql`as (a + f)`))\n            .addColumn('z', 'varbinary')\n            .addColumn('aa', 'varbinary(16)')\n\n          testSql(builder, dialect, {\n            mssql: {\n              sql: [\n                'create table \"test\"',\n                '(\"a\" integer identity not null primary key,',\n                '\"b\" integer references \"test\" (\"a\") on delete no action on update no action check (b < 10),',\n                '\"c\" varchar,',\n                '\"d\" varchar(10),',\n                '\"e\" bigint not null unique,',\n                '\"f\" double precision,',\n                '\"g\" real,',\n                '\"h\" text,',\n                '\"i\" varchar(123),',\n                '\"j\" numeric(6, 2),',\n                '\"k\" decimal(8, 4),',\n                '\"l\" bit default 0 not null,',\n                '\"m\" date,',\n                '\"n\" datetime default current_timestamp,',\n                '\"o\" uniqueidentifier default newid() not null,',\n                '\"p\" smallint,',\n                '\"q\" int,',\n                '\"r\" double precision not null,',\n                '\"s\" time(6),',\n                '\"t\" timestamp not null,',\n                '\"u\" datetime2,',\n                '\"v\" char(4),',\n                '\"w\" char,',\n                '\"x\" binary,',\n                '\"y\"  as (a + f),',\n                '\"z\" varbinary,',\n                '\"aa\" varbinary(16))',\n              ],\n              parameters: [],\n            },\n            postgres: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      } else if (dialect === 'sqlite') {\n        it('should create a table with all data types', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer', (col) =>\n              col.primaryKey().autoIncrement().notNull(),\n            )\n            .addColumn('b', 'integer', (col) =>\n              col\n                .references('test.a')\n                .onDelete('cascade')\n                .onUpdate('restrict')\n                .check(sql`b < a`),\n            )\n            .addColumn('c', 'varchar')\n            .addColumn('d', 'varchar(10)')\n            .addColumn('e', 'bigint', (col) => col.unique().notNull())\n            .addColumn('f', 'double precision')\n            .addColumn('g', 'real')\n            .addColumn('h', 'text')\n            .addColumn('i', sql`varchar(123)`)\n            .addColumn('j', 'numeric(6, 2)')\n            .addColumn('k', 'decimal(8, 4)')\n            .addColumn('l', 'boolean', (col) => col.notNull().defaultTo(false))\n            .addColumn('m', 'date')\n            .addColumn('n', 'timestamptz')\n            .addColumn('o', 'int2')\n            .addColumn('p', 'int4')\n            .addColumn('q', 'int8')\n            .addColumn('r', 'double precision', (col) =>\n              col\n                .generatedAlwaysAs(sql`f + g`)\n                .stored()\n                .notNull(),\n            )\n            .addColumn('s', 'blob')\n\n          testSql(builder, dialect, {\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: [\n                'create table \"test\"',\n                '(\"a\" integer not null primary key autoincrement,',\n                '\"b\" integer references \"test\" (\"a\") on delete cascade on update restrict check (b < a),',\n                '\"c\" varchar,',\n                '\"d\" varchar(10),',\n                '\"e\" bigint not null unique,',\n                '\"f\" double precision,',\n                '\"g\" real,',\n                '\"h\" text,',\n                '\"i\" varchar(123),',\n                '\"j\" numeric(6, 2),',\n                '\"k\" decimal(8, 4),',\n                '\"l\" boolean default false not null,',\n                '\"m\" date,',\n                '\"n\" timestamptz,',\n                '\"o\" int2,',\n                '\"p\" int4,',\n                '\"q\" int8,',\n                '\"r\" double precision generated always as (f + g) stored not null,',\n                '\"s\" blob)',\n              ],\n              parameters: [],\n            },\n            postgres: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n\n          expect(await getColumnMeta('test.a')).to.eql({\n            comment: undefined,\n            dataType: 'INTEGER',\n            isAutoIncrementing: true,\n            isNullable: false,\n            hasDefaultValue: false,\n            name: 'a',\n          })\n\n          expect(await getColumnMeta('test.b')).to.eql({\n            comment: undefined,\n            dataType: 'INTEGER',\n            isAutoIncrementing: false,\n            isNullable: true,\n            hasDefaultValue: false,\n            name: 'b',\n          })\n\n          expect(await getColumnMeta('test.l')).to.eql({\n            comment: undefined,\n            dataType: 'boolean',\n            isAutoIncrementing: false,\n            isNullable: false,\n            hasDefaultValue: true,\n            name: 'l',\n          })\n        })\n      } else {\n        throw new Error(`Unknown dialect: ${dialect}`)\n      }\n\n      it('should create a table with a unique constraints', async () => {\n        const builder = ctx.db.schema\n          .createTable('test')\n          .addColumn('a', 'varchar(255)')\n          .addColumn('b', 'varchar(255)')\n          .addColumn('c', 'varchar(255)')\n          .addUniqueConstraint('a_b_unique', ['a', 'b'])\n          .addUniqueConstraint('b_c_unique', ['b', 'c'])\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create table \"test\" (\"a\" varchar(255), \"b\" varchar(255), \"c\" varchar(255), constraint \"a_b_unique\" unique (\"a\", \"b\"), constraint \"b_c_unique\" unique (\"b\", \"c\"))',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create table `test` (`a` varchar(255), `b` varchar(255), `c` varchar(255), constraint `a_b_unique` unique (`a`, `b`), constraint `b_c_unique` unique (`b`, `c`))',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create table \"test\" (\"a\" varchar(255), \"b\" varchar(255), \"c\" varchar(255), constraint \"a_b_unique\" unique (\"a\", \"b\"), constraint \"b_c_unique\" unique (\"b\", \"c\"))',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create table \"test\" (\"a\" varchar(255), \"b\" varchar(255), \"c\" varchar(255), constraint \"a_b_unique\" unique (\"a\", \"b\"), constraint \"b_c_unique\" unique (\"b\", \"c\"))',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (dialect === 'postgres') {\n        it('should create a table with a unique constraint and \"nulls not distinct\" option', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'varchar(255)')\n            .addColumn('b', 'varchar(255)')\n            .addUniqueConstraint('a_b_unique', ['a', 'b'], (uc) =>\n              uc.nullsNotDistinct(),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" varchar(255), \"b\" varchar(255), constraint \"a_b_unique\" unique nulls not distinct (\"a\", \"b\"))',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a table with deferrable unique constraints', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'varchar(255)')\n            .addColumn('b', 'varchar(255)')\n            .addUniqueConstraint('unique_1', ['a', 'b'], (uc) =>\n              uc.deferrable(),\n            )\n            .addUniqueConstraint('unique_2', ['a', 'b'], (uc) =>\n              uc.notDeferrable(),\n            )\n            .addUniqueConstraint('unique_3', ['a', 'b'], (uc) =>\n              uc.deferrable().initiallyDeferred(),\n            )\n            .addUniqueConstraint('unique_4', ['a', 'b'], (uc) =>\n              uc.deferrable().initiallyImmediate(),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" varchar(255), \"b\" varchar(255), constraint \"unique_1\" unique (\"a\", \"b\") deferrable, constraint \"unique_2\" unique (\"a\", \"b\") not deferrable, constraint \"unique_3\" unique (\"a\", \"b\") deferrable initially deferred, constraint \"unique_4\" unique (\"a\", \"b\") deferrable initially immediate)',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      it('should create a table with check constraints', async () => {\n        const builder = ctx.db.schema\n          .createTable('test')\n          .addColumn('a', 'integer')\n          .addColumn('b', 'integer')\n          .addColumn('c', 'integer')\n          .addCheckConstraint('check_a', sql`a > 1`)\n          .addCheckConstraint('check_b', sql`b < c`)\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, \"c\" integer, constraint \"check_a\" check (a > 1), constraint \"check_b\" check (b < c))',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create table `test` (`a` integer, `b` integer, `c` integer, constraint `check_a` check (a > 1), constraint `check_b` check (b < c))',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, \"c\" integer, constraint \"check_a\" check (a > 1), constraint \"check_b\" check (b < c))',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, \"c\" integer, constraint \"check_a\" check (a > 1), constraint \"check_b\" check (b < c))',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      it('should create a table with a composite primary key constraint', async () => {\n        const builder = ctx.db.schema\n          .createTable('test')\n          .addColumn('a', 'integer')\n          .addColumn('b', 'integer')\n          .addPrimaryKeyConstraint('primary', ['a', 'b'])\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"primary\" primary key (\"a\", \"b\"))',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create table `test` (`a` integer, `b` integer, constraint `primary` primary key (`a`, `b`))',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"primary\" primary key (\"a\", \"b\"))',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"primary\" primary key (\"a\", \"b\"))',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (dialect === 'postgres') {\n        it('should create a table with a deferrable primary key constraint', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer')\n            .addPrimaryKeyConstraint('primary', ['a'], (pk) => pk.deferrable())\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" integer, constraint \"primary\" primary key (\"a\") deferrable)',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a table with not deferrable primary key constraint', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer')\n            .addPrimaryKeyConstraint('primary', ['a'], (pk) =>\n              pk.notDeferrable(),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" integer, constraint \"primary\" primary key (\"a\") not deferrable)',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a table with a deferrable initially deferred primary key constraint', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer')\n            .addPrimaryKeyConstraint('primary', ['a'], (pk) =>\n              pk.deferrable().initiallyDeferred(),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" integer, constraint \"primary\" primary key (\"a\") deferrable initially deferred)',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a table with a deferrable initially immediate primary key constraint', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer')\n            .addPrimaryKeyConstraint('primary', ['a'], (pk) =>\n              pk.deferrable().initiallyImmediate(),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" integer, constraint \"primary\" primary key (\"a\") deferrable initially immediate)',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      it('should create a table with a foreign key constraint', async () => {\n        await ctx.db.schema\n          .createTable('test2')\n          .addColumn('c', 'integer')\n          .addColumn('d', 'integer')\n          .addPrimaryKeyConstraint('primary_key', ['c', 'd'])\n          .execute()\n\n        const builder = ctx.db.schema\n          .createTable('test')\n          .addColumn('a', 'integer')\n          .addColumn('b', 'integer')\n          .addForeignKeyConstraint('foreign_key', ['a', 'b'], 'test2', [\n            'c',\n            'd',\n          ])\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\"))',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create table `test` (`a` integer, `b` integer, constraint `foreign_key` foreign key (`a`, `b`) references `test2` (`c`, `d`))',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\"))',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\"))',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (dialect !== 'mysql' && dialect !== 'mssql') {\n        it('should create a table with deferrable foreign key constraints', async () => {\n          await ctx.db.schema\n            .createTable('test2')\n            .addColumn('c', 'integer')\n            .addColumn('d', 'integer')\n            .addPrimaryKeyConstraint('primary_key', ['c', 'd'])\n            .execute()\n\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer')\n            .addColumn('b', 'integer')\n            .addForeignKeyConstraint(\n              'foreign_key',\n              ['a', 'b'],\n              'test2',\n              ['c', 'd'],\n              (fk) => fk.deferrable(),\n            )\n            .addForeignKeyConstraint(\n              'foreign_key_2',\n              ['a', 'b'],\n              'test2',\n              ['c', 'd'],\n              (fk) => fk.notDeferrable(),\n            )\n            .addForeignKeyConstraint(\n              'foreign_key_3',\n              ['a', 'b'],\n              'test2',\n              ['c', 'd'],\n              (fk) => fk.deferrable().initiallyDeferred(),\n            )\n            .addForeignKeyConstraint(\n              'foreign_key_4',\n              ['a', 'b'],\n              'test2',\n              ['c', 'd'],\n              (fk) => fk.deferrable().initiallyImmediate(),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") deferrable, constraint \"foreign_key_2\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") not deferrable, constraint \"foreign_key_3\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") deferrable initially deferred, constraint \"foreign_key_4\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") deferrable initially immediate)',\n              parameters: [],\n            },\n            sqlite: {\n              sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") deferrable, constraint \"foreign_key_2\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") not deferrable, constraint \"foreign_key_3\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") deferrable initially deferred, constraint \"foreign_key_4\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") deferrable initially immediate)',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres' || dialect === 'mssql') {\n        it('should support schemas in foreign key target table', async () => {\n          await ctx.db.schema\n            .createTable('test2')\n            .addColumn('c', 'integer')\n            .addColumn('d', 'integer')\n            .addPrimaryKeyConstraint('primary_key', ['c', 'd'])\n            .execute()\n\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('a', 'integer')\n            .addColumn('b', 'integer')\n            .addForeignKeyConstraint(\n              'foreign_key',\n              ['a', 'b'],\n              dialect === 'postgres' ? 'public.test2' : 'dbo.test2',\n              ['c', 'd'],\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"public\".\"test2\" (\"c\", \"d\"))',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"dbo\".\"test2\" (\"c\", \"d\"))',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      it('should create a table with a foreign key constraint that has an `on update` statement', async () => {\n        await ctx.db.schema\n          .createTable('test2')\n          .addColumn('c', 'integer')\n          .addColumn('d', 'integer')\n          .addPrimaryKeyConstraint('primary_key', ['c', 'd'])\n          .execute()\n\n        const builder = ctx.db.schema\n          .createTable('test')\n          .addColumn('a', 'integer')\n          .addColumn('b', 'integer')\n          .addForeignKeyConstraint(\n            'foreign_key',\n            ['a', 'b'],\n            'test2',\n            ['c', 'd'],\n            (cb) => cb.onUpdate('cascade'),\n          )\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") on update cascade)',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create table `test` (`a` integer, `b` integer, constraint `foreign_key` foreign key (`a`, `b`) references `test2` (`c`, `d`) on update cascade)',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") on update cascade)',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create table \"test\" (\"a\" integer, \"b\" integer, constraint \"foreign_key\" foreign key (\"a\", \"b\") references \"test2\" (\"c\", \"d\") on update cascade)',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'sqlite'\n      ) {\n        it(\"should create a table if it doesn't already exist\", async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .ifNotExists()\n            .addColumn('id', 'integer', (col) => col.primaryKey())\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table if not exists \"test\" (\"id\" integer primary key)',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'create table if not exists `test` (`id` integer primary key)',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'create table if not exists \"test\" (\"id\" integer primary key)',\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a temporary table', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .temporary()\n            .addColumn('id', 'integer', (col) => col.primaryKey())\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create temporary table \"test\" (\"id\" integer primary key)',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'create temporary table `test` (`id` integer primary key)',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'create temporary table \"test\" (\"id\" integer primary key)',\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a table with as expression', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .as(ctx.db.selectFrom('person').select(['first_name', 'last_name']))\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" as select \"first_name\", \"last_name\" from \"person\"',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'create table `test` as select `first_name`, `last_name` from `person`',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'create table \"test\" as select \"first_name\", \"last_name\" from \"person\"',\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a temporary table if not exists with as expression', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .temporary()\n            .ifNotExists()\n            .as(\n              ctx.db\n                .selectFrom('person')\n                .select(['first_name', 'last_name'])\n                .where('first_name', '=', 'Jennifer'),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create temporary table if not exists \"test\" as select \"first_name\", \"last_name\" from \"person\" where \"first_name\" = $1',\n              parameters: ['Jennifer'],\n            },\n            mysql: {\n              sql: 'create temporary table if not exists `test` as select `first_name`, `last_name` from `person` where `first_name` = ?',\n              parameters: ['Jennifer'],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'create temporary table if not exists \"test\" as select \"first_name\", \"last_name\" from \"person\" where \"first_name\" = ?',\n              parameters: ['Jennifer'],\n            },\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a table with as expression and raw sql', async () => {\n          let rawSql = sql`select \"first_name\", \"last_name\" from \"person\"`\n          if (dialect === 'mysql') {\n            rawSql = sql`select \\`first_name\\`, \\`last_name\\` from \\`person\\``\n          }\n\n          const builder = ctx.db.schema.createTable('test').as(rawSql)\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" as select \"first_name\", \"last_name\" from \"person\"',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'create table `test` as select `first_name`, `last_name` from `person`',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'create table \"test\" as select \"first_name\", \"last_name\" from \"person\"',\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a table with as expression and ignore addColumn', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .as(ctx.db.selectFrom('person').select(['first_name', 'last_name']))\n            .addColumn('first_name', 'varchar(20)')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" as select \"first_name\", \"last_name\" from \"person\"',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'create table `test` as select `first_name`, `last_name` from `person`',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'create table \"test\" as select \"first_name\", \"last_name\" from \"person\"',\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'mssql') {\n        it('should create a temporary table', async () => {\n          await ctx.db.connection().execute(async (conn) => {\n            const builder = conn.schema\n              .createTable('##test')\n              .addColumn('id', 'integer', (col) => col.primaryKey())\n\n            testSql(builder, dialect, {\n              postgres: NOT_SUPPORTED,\n              mysql: NOT_SUPPORTED,\n              mssql: {\n                sql: 'create table \"##test\" (\"id\" integer primary key)',\n                parameters: [],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n\n            await sql`select * from \"##test\"`.execute(conn)\n          })\n\n          try {\n            await sql`select * from \"##test\"`.execute(ctx.db)\n\n            fail() // table is not gone!\n          } catch (err) {\n            // it works!\n          }\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should create a temporary table with on commit statement', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .temporary()\n            .addColumn('id', 'integer', (col) => col.primaryKey())\n            .onCommit('drop')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create temporary table \"test\" (\"id\" integer primary key) on commit drop',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a temporary table with on commit and as expression', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .temporary()\n            .onCommit('drop')\n            .as(\n              ctx.db\n                .selectFrom('person')\n                .select(['first_name', 'last_name'])\n                .where('first_name', '=', 'Jennifer'),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create temporary table \"test\" on commit drop as select \"first_name\", \"last_name\" from \"person\" where \"first_name\" = $1',\n              parameters: ['Jennifer'],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres' || dialect === 'mssql') {\n        const schema = dialect === 'postgres' ? 'public' : 'dbo'\n\n        it('should create a table in specific schema', async () => {\n          const builder = ctx.db.schema\n            .createTable(`${schema}.test`)\n            .addColumn('id', 'varchar(32)', (col) => col.primaryKey())\n            .addColumn('foreign_key', 'varchar(32)', (col) =>\n              col.references(`${schema}.test.id`),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"public\".\"test\" (\"id\" varchar(32) primary key, \"foreign_key\" varchar(32) references \"public\".\"test\" (\"id\"))',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'create table \"dbo\".\"test\" (\"id\" varchar(32) primary key, \"foreign_key\" varchar(32) references \"dbo\".\"test\" (\"id\"))',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should create a table with generated identity', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('id', 'integer', (col) =>\n              col.generatedAlwaysAsIdentity(),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"id\" integer generated always as identity)',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should create a table with generated identity (by default)', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('id', 'integer', (col) =>\n              col.generatedByDefaultAsIdentity(),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create table \"test\" (\"id\" integer generated by default as identity)',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should create a global temporary table', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .modifyFront(sql`global temporary`)\n            .addColumn('id', 'integer', (col) => col.primaryKey())\n            .addColumn('first_name', 'varchar(64)', (col) => col.notNull())\n            .addColumn('last_name', 'varchar(64)', (col) => col.notNull())\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: [\n                'create global temporary table \"test\"',\n                '(\"id\" integer primary key,',\n                '\"first_name\" varchar(64) not null,',\n                '\"last_name\" varchar(64) not null)',\n              ],\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should create a table partitioned by country', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('id', 'integer', (col) => col.notNull())\n            .addColumn('nickname', 'varchar(64)', (col) => col.notNull())\n            .addColumn('country', 'varchar(2)', (col) => col.notNull())\n            .addPrimaryKeyConstraint('test_pk', ['id', 'country'])\n            .modifyEnd(sql`partition by hash (${sql.ref('country')})`)\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: [\n                'create table \"test\"',\n                '(\"id\" integer not null,',\n                '\"nickname\" varchar(64) not null,',\n                '\"country\" varchar(2) not null,',\n                'constraint \"test_pk\" primary key (\"id\", \"country\")) partition by hash (\"country\")',\n              ],\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'mysql') {\n        it('should create a table partitioned by country', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('id', 'integer', (col) => col.notNull())\n            .addColumn('nickname', 'varchar(64)', (col) => col.notNull())\n            .addColumn('country', 'varchar(2)', (col) => col.notNull())\n            .addPrimaryKeyConstraint('test_pk', ['id', 'country'])\n            .modifyEnd(sql`partition by key (${sql.ref('country')})`)\n\n          testSql(builder, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              sql: [\n                'create table `test`',\n                '(`id` integer not null,',\n                '`nickname` varchar(64) not null,',\n                '`country` varchar(2) not null,',\n                'constraint `test_pk` primary key (`id`, `country`)) partition by key (`country`)',\n              ],\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'sqlite') {\n        it('should create a strict table', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('id', 'integer', (col) => col.primaryKey())\n            .addColumn('nickname', 'text', (col) => col.notNull())\n            .addColumn('country', 'text', (col) => col.notNull())\n            .modifyEnd(sql`strict`)\n\n          testSql(builder, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: [\n                'create table \"test\"',\n                '(\"id\" integer primary key,',\n                '\"nickname\" text not null,',\n                '\"country\" text not null) strict',\n              ],\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'mysql') {\n        it('should create a table while using modifiers to define columns', async () => {\n          const builder = ctx.db.schema\n            .createTable('test')\n            .addColumn('id', 'integer', (col) => col.primaryKey())\n            .addColumn('first_name', 'varchar(36)', (col) =>\n              col.modifyFront(sql`collate utf8mb4_general_ci`).notNull(),\n            )\n            .addColumn('age', 'integer', (col) =>\n              col\n                .unsigned()\n                .notNull()\n                .modifyEnd(\n                  sql`comment ${sql.lit(\n                    'it is not polite to ask a woman her age',\n                  )}`,\n                ),\n            )\n\n          testSql(builder, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: {\n              sql: [\n                'create table `test`',\n                '(`id` integer primary key,',\n                '`first_name` varchar(36) collate utf8mb4_general_ci not null,',\n                \"`age` integer unsigned not null comment 'it is not polite to ask a woman her age')\",\n              ],\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      it('should create a table calling query builder functions', async () => {\n        const builder = ctx.db.schema\n          .createTable('test')\n          .addColumn('id', 'integer', (col) => col.notNull())\n          .$call((builder) =>\n            builder.addColumn('call_me', 'varchar(10)', (col) =>\n              col.defaultTo('maybe'),\n            ),\n          )\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: [\n              'create table \"test\"',\n              '(\"id\" integer not null,',\n              `\"call_me\" varchar(10) default 'maybe')`,\n            ],\n            parameters: [],\n          },\n          mysql: {\n            sql: [\n              'create table `test`',\n              '(`id` integer not null,',\n              \"`call_me` varchar(10) default 'maybe')\",\n            ],\n            parameters: [],\n          },\n          mssql: {\n            sql: [\n              'create table \"test\"',\n              '(\"id\" integer not null,',\n              `\"call_me\" varchar(10) default 'maybe')`,\n            ],\n            parameters: [],\n          },\n          sqlite: {\n            sql: [\n              'create table \"test\"',\n              '(\"id\" integer not null,',\n              `\"call_me\" varchar(10) default 'maybe')`,\n            ],\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n    })\n\n    describe('drop table', () => {\n      beforeEach(async () => {\n        await ctx.db.schema\n          .createTable('test')\n          .addColumn('id', 'bigint', (col) => col.primaryKey())\n          .execute()\n      })\n\n      it('should drop a table', async () => {\n        const builder = ctx.db.schema.dropTable('test')\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'drop table \"test\"',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'drop table `test`',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'drop table \"test\"',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'drop table \"test\"',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      it('should drop a table if it exists', async () => {\n        const builder = ctx.db.schema.dropTable('test').ifExists()\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'drop table if exists \"test\"',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'drop table if exists `test`',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'drop table if exists \"test\"',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'drop table if exists \"test\"',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (dialect == 'postgres' || dialect === 'mysql' || dialect === 'mssql') {\n        it('should drop a table cascade', async () => {\n          const builder = ctx.db.schema.dropTable('test').cascade()\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'drop table \"test\" cascade',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'drop table `test` cascade',\n              parameters: [],\n            },\n            mssql: {\n              sql: 'drop table \"test\" cascade',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n        })\n\n        it('should drop a table cascade if it exists', async () => {\n          const builder = ctx.db.schema.dropTable('test').cascade().ifExists()\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'drop table if exists \"test\" cascade',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'drop table if exists `test` cascade',\n              parameters: [],\n            },\n            mssql: {\n              sql: 'drop table if exists \"test\" cascade',\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n        })\n      }\n    })\n\n    describe('create index', () => {\n      beforeEach(async () => {\n        await ctx.db.schema\n          .createTable('test')\n          .addColumn('id', 'bigint', (col) => col.primaryKey())\n          .addColumn('first_name', 'varchar(255)')\n          .addColumn('last_name', 'varchar(255)')\n          .addColumn('age', 'integer')\n          .execute()\n      })\n\n      it('should create an index', async () => {\n        const builder = ctx.db.schema\n          .createIndex('test_first_name_index')\n          .on('test')\n          .column('first_name')\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create index \"test_first_name_index\" on \"test\" (\"first_name\")',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create index `test_first_name_index` on `test` (`first_name`)',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create index \"test_first_name_index\" on \"test\" (\"first_name\")',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create index \"test_first_name_index\" on \"test\" (\"first_name\")',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (dialect === 'postgres' || dialect === 'sqlite') {\n        it('should create an index if not exists', async () => {\n          await ctx.db.schema\n            .createIndex('test_first_name_index')\n            .on('test')\n            .column('first_name')\n            .execute()\n\n          const builder = ctx.db.schema\n            .createIndex('test_first_name_index')\n            .ifNotExists()\n            .on('test')\n            .column('first_name')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create index if not exists \"test_first_name_index\" on \"test\" (\"first_name\")',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'create index if not exists \"test_first_name_index\" on \"test\" (\"first_name\")',\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n      }\n\n      it('should create a unique index', async () => {\n        const builder = ctx.db.schema\n          .createIndex('test_first_name_index')\n          .unique()\n          .on('test')\n          .column('first_name')\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create unique index \"test_first_name_index\" on \"test\" (\"first_name\")',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create unique index `test_first_name_index` on `test` (`first_name`)',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create unique index \"test_first_name_index\" on \"test\" (\"first_name\")',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create unique index \"test_first_name_index\" on \"test\" (\"first_name\")',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (dialect === 'postgres' || dialect === 'mysql') {\n        it('should create an index with a type', async () => {\n          const builder = ctx.db.schema\n            .createIndex('test_first_name_index')\n            .on('test')\n            .using('hash')\n            .column('first_name')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create index \"test_first_name_index\" on \"test\" using hash (\"first_name\")',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'create index `test_first_name_index` using hash on `test` (`first_name`)',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should create an index with \"nulls not distinct\" modifier', async () => {\n          const builder = ctx.db.schema\n            .createIndex('test_first_name_index')\n            .on('test')\n            .nullsNotDistinct()\n            .column('first_name')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'create index \"test_first_name_index\" on \"test\" (\"first_name\") nulls not distinct',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should create an index with \"nulls not distinct\" and other modifiers', async () => {\n          const builder = ctx.db.schema\n            .createIndex('test_first_last_name_index')\n            .nullsNotDistinct()\n            .ifNotExists()\n            .columns(['first_name', 'last_name'])\n            .using('btree')\n            .unique()\n            .where('first_name', 'like', 'test%')\n            .on('test')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql:\n                'create unique index if not exists \"test_first_last_name_index\" on \"test\" ' +\n                'using btree (\"first_name\", \"last_name\") nulls not distinct where \"first_name\" like \\'test%\\'',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      it('should create an index for multiple columns', async () => {\n        const builder = ctx.db.schema\n          .createIndex('test_name_index')\n          .on('test')\n          .columns(['first_name', 'last_name'])\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create index \"test_name_index\" on \"test\" (\"first_name\", \"last_name\")',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create index `test_name_index` on `test` (`first_name`, `last_name`)',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create index \"test_name_index\" on \"test\" (\"first_name\", \"last_name\")',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create index \"test_name_index\" on \"test\" (\"first_name\", \"last_name\")',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'sqlite'\n      ) {\n        it('should create an index for an expression', async () => {\n          const builder = ctx.db.schema\n            .createIndex('test_first_name_index')\n            .on('test')\n            .expression(sql`(first_name < 'Sami')`)\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create index \"test_first_name_index\" on \"test\" ((first_name < 'Sami'))`,\n              parameters: [],\n            },\n            mysql: {\n              sql: \"create index `test_first_name_index` on `test` ((first_name < 'Sami'))\",\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: `create index \"test_first_name_index\" on \"test\" ((first_name < 'Sami'))`,\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n      }\n\n      it('should create a sorted index, single column', async () => {\n        const builder = ctx.db.schema\n          .createIndex('test_descending_first_name_index')\n          .on('test')\n          .column('first_name desc')\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create index \"test_descending_first_name_index\" on \"test\" (\"first_name\" desc)',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create index `test_descending_first_name_index` on `test` (`first_name` desc)',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create index \"test_descending_first_name_index\" on \"test\" (\"first_name\" desc)',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create index \"test_descending_first_name_index\" on \"test\" (\"first_name\" desc)',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      it('should create a sorted index, multi-column', async () => {\n        const builder = ctx.db.schema\n          .createIndex('test_first_name_descending_last_name_index')\n          .on('test')\n          .columns(['first_name', 'last_name desc'])\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'create index \"test_first_name_descending_last_name_index\" on \"test\" (\"first_name\", \"last_name\" desc)',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'create index `test_first_name_descending_last_name_index` on `test` (`first_name`, `last_name` desc)',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'create index \"test_first_name_descending_last_name_index\" on \"test\" (\"first_name\", \"last_name\" desc)',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'create index \"test_first_name_descending_last_name_index\" on \"test\" (\"first_name\", \"last_name\" desc)',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mssql' ||\n        dialect === 'sqlite'\n      ) {\n        it('should create a partial index, single column', async () => {\n          const builder = ctx.db.schema\n            .createIndex('test_partial_index')\n            .on('test')\n            .column('first_name')\n            .where('first_name', '=', 'Sami')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create index \"test_partial_index\" on \"test\" (\"first_name\") where \"first_name\" = 'Sami'`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: `create index \"test_partial_index\" on \"test\" (\"first_name\") where \"first_name\" = 'Sami'`,\n              parameters: [],\n            },\n            sqlite: {\n              sql: `create index \"test_partial_index\" on \"test\" (\"first_name\") where \"first_name\" = 'Sami'`,\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n\n        it('should create a partial index, multi-column, and', async () => {\n          const builder = ctx.db.schema\n            .createIndex('test_partial_index')\n            .on('test')\n            .columns(['first_name', 'last_name'])\n            .where((eb) =>\n              eb.and([\n                eb('first_name', '=', 'Igal'),\n                eb(sql.ref('age'), '>=', 18),\n              ]),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create index \"test_partial_index\" on \"test\" (\"first_name\", \"last_name\") where (\"first_name\" = 'Igal' and \"age\" >= 18)`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: `create index \"test_partial_index\" on \"test\" (\"first_name\", \"last_name\") where (\"first_name\" = 'Igal' and \"age\" >= 18)`,\n              parameters: [],\n            },\n            sqlite: {\n              sql: `create index \"test_partial_index\" on \"test\" (\"first_name\", \"last_name\") where (\"first_name\" = 'Igal' and \"age\" >= 18)`,\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres' || dialect === 'sqlite') {\n        it('should create a partial index, multi-column, or', async () => {\n          const builder = ctx.db.schema\n            .createIndex('test_partial_index')\n            .on('test')\n            .columns(['first_name', 'last_name'])\n            .where((eb) =>\n              eb.or([\n                eb('first_name', '=', 'Igal'),\n                eb(sql.ref('age'), '>=', 18),\n              ]),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create index \"test_partial_index\" on \"test\" (\"first_name\", \"last_name\") where (\"first_name\" = 'Igal' or \"age\" >= 18)`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: `create index \"test_partial_index\" on \"test\" (\"first_name\", \"last_name\") where (\"first_name\" = 'Igal' or \"age\" >= 18)`,\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n      }\n    })\n\n    describe('drop index', () => {\n      beforeEach(async () => {\n        await ctx.db.schema\n          .createTable('test')\n          .addColumn('id', 'bigint', (col) => col.primaryKey())\n          .addColumn('first_name', 'varchar(255)')\n          .execute()\n\n        await ctx.db.schema\n          .createIndex('test_first_name_index')\n          .on('test')\n          .column('first_name')\n          .execute()\n      })\n\n      it('should drop an index', async () => {\n        let builder = ctx.db.schema.dropIndex('test_first_name_index')\n\n        if (dialect === 'mysql' || dialect === 'mssql') {\n          builder = builder.on('test')\n        }\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: 'drop index \"test_first_name_index\"',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'drop index `test_first_name_index` on `test`',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'drop index \"test_first_name_index\" on \"test\"',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'drop index \"test_first_name_index\"',\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mssql' ||\n        dialect === 'sqlite'\n      ) {\n        it('should drop an index if it exists', async () => {\n          let builder = ctx.db.schema\n            .dropIndex('test_first_name_index')\n            .ifExists()\n\n          if (dialect === 'mssql') {\n            builder = builder.on('test')\n          }\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'drop index if exists \"test_first_name_index\"',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: {\n              sql: 'drop index if exists \"test_first_name_index\" on \"test\"',\n              parameters: [],\n            },\n            sqlite: {\n              sql: 'drop index if exists \"test_first_name_index\"',\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should drop an index cascade', async () => {\n          let builder = ctx.db.schema\n            .dropIndex('test_first_name_index')\n            .cascade()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'drop index \"test_first_name_index\" cascade',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should drop an index cascade if it exists', async () => {\n          let builder = ctx.db.schema\n            .dropIndex('test_first_name_index')\n            .cascade()\n            .ifExists()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'drop index if exists \"test_first_name_index\" cascade',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n    })\n\n    describe('create view', () => {\n      beforeEach(cleanup)\n      afterEach(cleanup)\n\n      it('should create a view', async () => {\n        const builder = ctx.db.schema\n          .createView('dogs')\n          .as(ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'))\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: `create view \"dogs\" as select * from \"pet\" where \"species\" = 'dog'`,\n            parameters: [],\n          },\n          mysql: {\n            sql: \"create view `dogs` as select * from `pet` where `species` = 'dog'\",\n            parameters: [],\n          },\n          mssql: {\n            sql: `create view \"dogs\" as select * from \"pet\" where \"species\" = 'dog'`,\n            parameters: [],\n          },\n          sqlite: {\n            sql: `create view \"dogs\" as select * from \"pet\" where \"species\" = 'dog'`,\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (dialect === 'postgres' || dialect === 'sqlite') {\n        it('should create a temporary view', async () => {\n          const builder = ctx.db.schema\n            .createView('dogs')\n            .temporary()\n            .as(\n              ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create temporary view \"dogs\" as select * from \"pet\" where \"species\" = 'dog'`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: `create temporary view \"dogs\" as select * from \"pet\" where \"species\" = 'dog'`,\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres' || dialect === 'mysql') {\n        it('should create or replace a view', async () => {\n          const builder = ctx.db.schema\n            .createView('dogs')\n            .orReplace()\n            .as(\n              ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create or replace view \"dogs\" as select * from \"pet\" where \"species\" = 'dog'`,\n              parameters: [],\n            },\n            mysql: {\n              sql: \"create or replace view `dogs` as select * from `pet` where `species` = 'dog'\",\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'sqlite') {\n        it(\"should create a view if it doesn't exists\", async () => {\n          const builder = ctx.db.schema\n            .createView('dogs')\n            .ifNotExists()\n            .as(\n              ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'),\n            )\n\n          testSql(builder, dialect, {\n            postgres: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: `create view if not exists \"dogs\" as select * from \"pet\" where \"species\" = 'dog'`,\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should create a materialized view', async () => {\n          const builder = ctx.db.schema\n            .createView('materialized_dogs')\n            .materialized()\n            .as(\n              ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create materialized view \"materialized_dogs\" as select * from \"pet\" where \"species\" = 'dog'`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      async function cleanup() {\n        await ctx.db.schema.dropView('dogs').ifExists().execute()\n\n        if (dialect === 'postgres') {\n          await ctx.db.schema\n            .dropView('materialized_dogs')\n            .materialized()\n            .ifExists()\n            .execute()\n        }\n      }\n    })\n\n    describe('refresh materialized view', () => {\n      beforeEach(async () => {\n        await ctx.db.schema\n          .createView('materialized_dogs')\n          .materialized()\n          .as(ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'))\n          .execute()\n      })\n\n      afterEach(async () => {\n        await ctx.db.schema\n          .dropView('materialized_dogs')\n          .materialized()\n          .ifExists()\n          .execute()\n      })\n\n      if (dialect === 'postgres') {\n        it('should refresh a materialized view', async () => {\n          const builder =\n            ctx.db.schema.refreshMaterializedView('materialized_dogs')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `refresh materialized view \"materialized_dogs\" with data`,\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should refresh a materialized view concurrently', async () => {\n          // concurrent refreshes require a unique index\n          await ctx.db.schema\n            .createIndex('materialized_dogs_index')\n            .unique()\n            .on('materialized_dogs')\n            .columns(['id'])\n            .execute()\n\n          const builder = ctx.db.schema\n            .refreshMaterializedView('materialized_dogs')\n            .concurrently()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `refresh materialized view concurrently \"materialized_dogs\" with data`,\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should refresh a materialized view with no data', async () => {\n          const builder = ctx.db.schema\n            .refreshMaterializedView('materialized_dogs')\n            .withNoData()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `refresh materialized view \"materialized_dogs\" with no data`,\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            mysql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n    })\n\n    describe('drop view', () => {\n      beforeEach(async () => {\n        await ctx.db.schema\n          .createView('dogs')\n          .as(ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'))\n          .execute()\n      })\n\n      afterEach(async () => {\n        await ctx.db.schema.dropView('dogs').ifExists().execute()\n      })\n\n      it('should drop a view', async () => {\n        const builder = ctx.db.schema.dropView('dogs')\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: `drop view \"dogs\"`,\n            parameters: [],\n          },\n          mysql: {\n            sql: 'drop view `dogs`',\n            parameters: [],\n          },\n          mssql: {\n            sql: `drop view \"dogs\"`,\n            parameters: [],\n          },\n          sqlite: {\n            sql: `drop view \"dogs\"`,\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      it('should drop a view if it exists', async () => {\n        const builder = ctx.db.schema.dropView('dogs').ifExists()\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: `drop view if exists \"dogs\"`,\n            parameters: [],\n          },\n          mysql: {\n            sql: 'drop view if exists `dogs`',\n            parameters: [],\n          },\n          mssql: {\n            sql: `drop view if exists \"dogs\"`,\n            parameters: [],\n          },\n          sqlite: {\n            sql: `drop view if exists \"dogs\"`,\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (dialect === 'postgres' || dialect === 'mysql') {\n        it('should drop a view cascade', async () => {\n          const builder = ctx.db.schema.dropView('dogs').cascade()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `drop view \"dogs\" cascade`,\n              parameters: [],\n            },\n            mysql: {\n              sql: 'drop view `dogs` cascade',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should drop a view cascade if it exists', async () => {\n          const builder = ctx.db.schema.dropView('dogs').ifExists().cascade()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `drop view if exists \"dogs\" cascade`,\n              parameters: [],\n            },\n            mysql: {\n              sql: 'drop view if exists `dogs` cascade',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n    })\n\n    describe('create schema', () => {\n      beforeEach(cleanup)\n      afterEach(cleanup)\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'mssql'\n      ) {\n        it('should create a schema', async () => {\n          const builder = ctx.db.schema.createSchema('pets')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create schema \"pets\"`,\n              parameters: [],\n            },\n            mysql: {\n              sql: 'create schema `pets`',\n              parameters: [],\n            },\n            mssql: {\n              sql: `create schema \"pets\"`,\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres' || dialect === 'mysql') {\n        it('should create a schema if not exists', async () => {\n          const builder = ctx.db.schema.createSchema('pets').ifNotExists()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create schema if not exists \"pets\"`,\n              parameters: [],\n            },\n            mysql: {\n              sql: 'create schema if not exists `pets`',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      async function cleanup() {\n        await ctx.db.schema.dropSchema('pets').ifExists().execute()\n      }\n    })\n\n    describe('drop schema', () => {\n      beforeEach(cleanup)\n      afterEach(cleanup)\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'mssql'\n      ) {\n        it('should drop a schema', async () => {\n          await ctx.db.schema.createSchema('pets').execute()\n\n          const builder = ctx.db.schema.dropSchema('pets')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `drop schema \"pets\"`,\n              parameters: [],\n            },\n            mysql: {\n              sql: 'drop schema `pets`',\n              parameters: [],\n            },\n            mssql: {\n              sql: `drop schema \"pets\"`,\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should drop a schema if exists', async () => {\n          const builder = ctx.db.schema.dropSchema('pets').ifExists()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `drop schema if exists \"pets\"`,\n              parameters: [],\n            },\n            mysql: {\n              sql: 'drop schema if exists `pets`',\n              parameters: [],\n            },\n            mssql: {\n              sql: `drop schema if exists \"pets\"`,\n              parameters: [],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should drop a schema cascade', async () => {\n          await ctx.db.schema.createSchema('pets').execute()\n          const builder = ctx.db.schema.dropSchema('pets').cascade()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `drop schema \"pets\" cascade`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should drop a schema cascade if exists', async () => {\n          const builder = ctx.db.schema.dropSchema('pets').cascade().ifExists()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `drop schema if exists \"pets\" cascade`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      async function cleanup() {\n        await ctx.db.schema.dropSchema('pets').ifExists().execute()\n      }\n    })\n\n    describe('create type', () => {\n      if (dialect === 'postgres') {\n        beforeEach(cleanup)\n        afterEach(cleanup)\n\n        it('should create an enum type', async () => {\n          const builder = ctx.db.schema\n            .createType('species')\n            .asEnum(['cat', 'dog', 'frog'])\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `create type \"species\" as enum ('cat', 'dog', 'frog')`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      async function cleanup() {\n        await ctx.db.schema.dropType('species').ifExists().execute()\n      }\n    })\n\n    describe('drop type', () => {\n      if (dialect === 'postgres') {\n        beforeEach(cleanup)\n        afterEach(cleanup)\n\n        it('should drop a type', async () => {\n          await ctx.db.schema.createType('species').execute()\n\n          const builder = ctx.db.schema.dropType('species')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `drop type \"species\"`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n\n        it('should drop a type if exists', async () => {\n          const builder = ctx.db.schema.dropType('species').ifExists()\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: `drop type if exists \"species\"`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      async function cleanup() {\n        await ctx.db.schema.dropType('species').ifExists().execute()\n      }\n    })\n\n    describe('alter table', () => {\n      beforeEach(async () => {\n        await ctx.db.schema\n          .createTable('test')\n          .addColumn('varchar_col', 'varchar(255)')\n          .addColumn('integer_col', 'integer')\n          .execute()\n      })\n\n      describe('add column', () => {\n        it('should add a column', async () => {\n          const builder = ctx.db.schema\n            .alterTable('test')\n            .addColumn('date_col', 'date', (cb) => cb.notNull())\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'alter table \"test\" add column \"date_col\" date not null',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'alter table `test` add column `date_col` date not null',\n              parameters: [],\n            },\n            mssql: {\n              sql: 'alter table \"test\" add \"date_col\" date not null',\n              parameters: [],\n            },\n            sqlite: {\n              sql: 'alter table \"test\" add column \"date_col\" date not null',\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n\n        if (dialect === 'postgres') {\n          it('should add a column with \"unique nulls not distinct\" modifier', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addColumn('desc', 'varchar(20)', (cb) =>\n                cb.unique().nullsNotDistinct(),\n              )\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" add column \"desc\" varchar(20) unique nulls not distinct',\n                parameters: [],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n\n          it('should add a column with \"if not exists\" modifier', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addColumn('desc', 'varchar(20)', (cb) => cb.ifNotExists())\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" add column if not exists \"desc\" varchar(20)',\n                parameters: [],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n        }\n\n        if (dialect === 'postgres' || dialect === 'mysql') {\n          it('should add a unique column', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addColumn('bool_col', 'boolean', (cb) => cb.notNull().unique())\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" add column \"bool_col\" boolean not null unique',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` add column `bool_col` boolean not null unique',\n                parameters: [],\n              },\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n\n            expect(await getColumnMeta('test.bool_col')).to.containSubset({\n              name: 'bool_col',\n              isNullable: false,\n              dataType: dialect === 'postgres' ? 'bool' : 'tinyint',\n            })\n          })\n        }\n\n        if (\n          dialect === 'postgres' ||\n          dialect === 'mysql' ||\n          dialect === 'mssql'\n        ) {\n          it('should add multiple columns', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addColumn('another_col', 'text')\n              .addColumn('yet_another_col', 'integer')\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: [\n                  'alter table \"test\"',\n                  'add column \"another_col\" text,',\n                  'add column \"yet_another_col\" integer',\n                ],\n                parameters: [],\n              },\n              mysql: {\n                sql: [\n                  'alter table `test`',\n                  'add column `another_col` text,',\n                  'add column `yet_another_col` integer',\n                ],\n                parameters: [],\n              },\n              mssql: {\n                sql: [\n                  'alter table \"test\"',\n                  'add \"another_col\" text,',\n                  '\"yet_another_col\" integer',\n                ],\n                parameters: [],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n        }\n      })\n\n      if (dialect === 'mysql') {\n        describe('modify column', () => {\n          it('should set column data type', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .modifyColumn('varchar_col', 'text')\n\n            testSql(builder, dialect, {\n              postgres: NOT_SUPPORTED,\n              mysql: {\n                sql: 'alter table `test` modify column `varchar_col` text',\n                parameters: [],\n              },\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n\n          it('should add not null constraint for column', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .modifyColumn('varchar_col', 'varchar(255)', (cb) => cb.notNull())\n\n            testSql(builder, dialect, {\n              mysql: {\n                sql: 'alter table `test` modify column `varchar_col` varchar(255) not null',\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n\n          it('should drop not null constraint for column', async () => {\n            await ctx.db.schema\n              .alterTable('test')\n              .modifyColumn('varchar_col', 'varchar(255)', (cb) => cb.notNull())\n              .execute()\n\n            expect(\n              (await getColumnMeta('test.varchar_col')).isNullable,\n            ).to.equal(false)\n\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .modifyColumn('varchar_col', 'varchar(255)')\n\n            testSql(builder, dialect, {\n              mysql: {\n                sql: 'alter table `test` modify column `varchar_col` varchar(255)',\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n\n            expect(\n              (await getColumnMeta('test.varchar_col')).isNullable,\n            ).to.equal(true)\n          })\n\n          it('should modify multiple columns', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .modifyColumn('varchar_col', 'varchar(255)')\n              .modifyColumn('integer_col', 'bigint')\n\n            testSql(builder, dialect, {\n              mysql: {\n                sql: [\n                  'alter table `test`',\n                  'modify column `varchar_col` varchar(255),',\n                  'modify column `integer_col` bigint',\n                ],\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n        })\n      }\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'mssql'\n      ) {\n        describe('alter column', () => {\n          if (dialect === 'postgres' || dialect === 'mysql') {\n            it('should set default value', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .alterColumn('varchar_col', (ac) => ac.setDefault('foo'))\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: `alter table \"test\" alter column \"varchar_col\" set default 'foo'`,\n                  parameters: [],\n                },\n                mysql: {\n                  sql: \"alter table `test` alter column `varchar_col` set default 'foo'\",\n                  parameters: [],\n                },\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n\n            it('should drop default value', async () => {\n              const subject = 'varchar_col'\n\n              await ctx.db.schema\n                .alterTable('test')\n                .alterColumn(subject, (ac) => ac.setDefault('foo'))\n                .execute()\n\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .alterColumn(subject, (ac) => ac.dropDefault())\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" alter column \"varchar_col\" drop default',\n                  parameters: [],\n                },\n                mysql: {\n                  sql: 'alter table `test` alter column `varchar_col` drop default',\n                  parameters: [],\n                },\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n              await builder.execute()\n            })\n          }\n\n          if (dialect === 'postgres' || dialect === 'mssql') {\n            it('should set column data type', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .alterColumn('varchar_col', (ac) => ac.setDataType('text'))\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" alter column \"varchar_col\" type text',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'alter table \"test\" alter column \"varchar_col\" text',\n                  parameters: [],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n\n            it('should set column data type from expression', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .alterColumn('varchar_col', (ac) => ac.setDataType(sql`text`))\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" alter column \"varchar_col\" type text',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: {\n                  sql: 'alter table \"test\" alter column \"varchar_col\" text',\n                  parameters: [],\n                },\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n          }\n\n          if (dialect === 'postgres') {\n            it('should add not null constraint for column', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .alterColumn('varchar_col', (ac) => ac.setNotNull())\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" alter column \"varchar_col\" set not null',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n\n            it('should drop not null constraint for column', async () => {\n              await ctx.db.schema\n                .alterTable('test')\n                .alterColumn('varchar_col', (ac) => ac.setNotNull())\n                .execute()\n\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .alterColumn('varchar_col', (ac) => ac.dropNotNull())\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" alter column \"varchar_col\" drop not null',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n          }\n\n          if (dialect === 'postgres' || dialect === 'mysql') {\n            it('should alter multiple columns', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .alterColumn('varchar_col', (ac) => ac.setDefault('foo'))\n                .alterColumn('integer_col', (ac) => ac.setDefault(5))\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: [\n                    `alter table \"test\"`,\n                    `alter column \"varchar_col\" set default 'foo',`,\n                    `alter column \"integer_col\" set default 5`,\n                  ],\n                  parameters: [],\n                },\n                mysql: {\n                  sql: [\n                    'alter table `test`',\n                    \"alter column `varchar_col` set default 'foo',\",\n                    'alter column `integer_col` set default 5',\n                  ],\n                  parameters: [],\n                },\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n          }\n        })\n      }\n\n      describe('drop column', () => {\n        it('should drop a column', async () => {\n          const builder = ctx.db.schema\n            .alterTable('test')\n            .dropColumn('varchar_col')\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'alter table \"test\" drop column \"varchar_col\"',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'alter table `test` drop column `varchar_col`',\n              parameters: [],\n            },\n            mssql: {\n              sql: 'alter table \"test\" drop column \"varchar_col\"',\n              parameters: [],\n            },\n            sqlite: {\n              sql: 'alter table \"test\" drop column \"varchar_col\"',\n              parameters: [],\n            },\n          })\n\n          await builder.execute()\n        })\n\n        if (\n          dialect === 'postgres' ||\n          dialect === 'mysql' ||\n          dialect === 'mssql'\n        ) {\n          it('should drop multiple columns', async () => {\n            await ctx.db.schema\n              .alterTable('test')\n              .addColumn('text_col', 'text')\n              .execute()\n\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .dropColumn('varchar_col')\n              .dropColumn('text_col')\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: [\n                  'alter table \"test\"',\n                  'drop column \"varchar_col\",',\n                  'drop column \"text_col\"',\n                ],\n                parameters: [],\n              },\n              mysql: {\n                sql: [\n                  'alter table `test`',\n                  'drop column `varchar_col`,',\n                  'drop column `text_col`',\n                ],\n                parameters: [],\n              },\n              mssql: {\n                sql: [\n                  'alter table \"test\"',\n                  'drop column \"varchar_col\",',\n                  '\"text_col\"',\n                ],\n                parameters: [],\n              },\n              sqlite: {\n                sql: [\n                  'alter table \"test\"',\n                  'drop column \"varchar_col\",',\n                  'drop column \"text_col\"',\n                ],\n                parameters: [],\n              },\n            })\n\n            await builder.execute()\n          })\n        }\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'sqlite'\n      ) {\n        describe('rename', () => {\n          it('should rename a table', async () => {\n            const builder = ctx.db.schema.alterTable('test').renameTo('test2')\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" rename to \"test2\"',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` rename to `test2`',\n                parameters: [],\n              },\n              mssql: NOT_SUPPORTED,\n              sqlite: {\n                sql: 'alter table \"test\" rename to \"test2\"',\n                parameters: [],\n              },\n            })\n\n            await builder.execute()\n          })\n        })\n      }\n\n      if (dialect === 'postgres') {\n        describe('set schema', () => {\n          it('should rename a table', async () => {\n            const builder = ctx.db.schema.alterTable('test').setSchema('public')\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" set schema \"public\"',\n                parameters: [],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n        })\n      }\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'sqlite'\n      ) {\n        describe('rename column', () => {\n          it('should rename a column', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .renameColumn('varchar_col', 'text_col')\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" rename column \"varchar_col\" to \"text_col\"',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` rename column `varchar_col` to `text_col`',\n                parameters: [],\n              },\n              mssql: NOT_SUPPORTED,\n              sqlite: {\n                sql: 'alter table \"test\" rename column \"varchar_col\" to \"text_col\"',\n                parameters: [],\n              },\n            })\n\n            await builder.execute()\n          })\n\n          if (dialect === 'mysql') {\n            it('should rename multiple columns', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .renameColumn('varchar_col', 'text_col')\n                .renameColumn('integer_col', 'number_col')\n\n              testSql(builder, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: {\n                  sql: [\n                    'alter table `test`',\n                    'rename column `varchar_col` to `text_col`,',\n                    'rename column `integer_col` to `number_col`',\n                  ],\n                  parameters: [],\n                },\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n          }\n        })\n      }\n\n      if (dialect === 'postgres' || dialect === 'mysql') {\n        describe('mixed column alterations', () => {\n          if (dialect === 'postgres') {\n            it('should alter multiple columns in various ways', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .addColumn('another_varchar_col', 'varchar(255)')\n                .alterColumn('varchar_col', (ac) => ac.setDefault('foo'))\n                .dropColumn('integer_col')\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: [\n                    `alter table \"test\"`,\n                    `add column \"another_varchar_col\" varchar(255),`,\n                    `alter column \"varchar_col\" set default 'foo',`,\n                    `drop column \"integer_col\"`,\n                  ],\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n          }\n\n          if (dialect === 'mysql') {\n            it('should alter multiple columns in various ways', async () => {\n              await ctx.db.schema\n                .alterTable('test')\n                .addColumn('rename_me', 'text')\n                .addColumn('modify_me', 'boolean')\n                .execute()\n\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .addColumn('another_varchar_col', 'varchar(255)')\n                .alterColumn('varchar_col', (ac) => ac.setDefault('foo'))\n                .dropColumn('integer_col')\n                .renameColumn('rename_me', 'text_col')\n                .modifyColumn('modify_me', 'bigint')\n\n              testSql(builder, dialect, {\n                postgres: NOT_SUPPORTED,\n                mysql: {\n                  sql: [\n                    'alter table `test`',\n                    'add column `another_varchar_col` varchar(255),',\n                    \"alter column `varchar_col` set default 'foo',\",\n                    'drop column `integer_col`,',\n                    'rename column `rename_me` to `text_col`,',\n                    'modify column `modify_me` bigint',\n                  ],\n                  parameters: [],\n                },\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n          }\n        })\n      }\n\n      if (dialect !== 'sqlite') {\n        describe('add unique constraint', () => {\n          it('should add a unique constraint', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addUniqueConstraint('some_constraint', [\n                'varchar_col',\n                'integer_col',\n              ])\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" unique (\"varchar_col\", \"integer_col\")',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` add constraint `some_constraint` unique (`varchar_col`, `integer_col`)',\n                parameters: [],\n              },\n              mssql: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" unique (\"varchar_col\", \"integer_col\")',\n                parameters: [],\n              },\n              sqlite: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" unique (\"varchar_col\", \"integer_col\")',\n                parameters: [],\n              },\n            })\n\n            await builder.execute()\n          })\n\n          if (dialect === 'postgres') {\n            it('should add a unique constraint with \"nulls not distinct\" modifier', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .addUniqueConstraint(\n                  'varchar_col_constaint',\n                  ['varchar_col'],\n                  (builder) => builder.nullsNotDistinct(),\n                )\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" add constraint \"varchar_col_constaint\" unique nulls not distinct (\"varchar_col\")',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n\n            it('should add a deferrable unique constraint', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .addUniqueConstraint(\n                  'some_constraint',\n                  ['varchar_col', 'integer_col'],\n                  (uc) => uc.deferrable(),\n                )\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" add constraint \"some_constraint\" unique (\"varchar_col\", \"integer_col\") deferrable',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n\n            it('should add a not deferrable unique constraint', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .addUniqueConstraint(\n                  'some_constraint',\n                  ['varchar_col', 'integer_col'],\n                  (uc) => uc.notDeferrable(),\n                )\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" add constraint \"some_constraint\" unique (\"varchar_col\", \"integer_col\") not deferrable',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n\n            it('should add a deferrable initially deferred unique constraint', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .addUniqueConstraint(\n                  'some_constraint',\n                  ['varchar_col', 'integer_col'],\n                  (uc) => uc.deferrable().initiallyDeferred(),\n                )\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" add constraint \"some_constraint\" unique (\"varchar_col\", \"integer_col\") deferrable initially deferred',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n\n            it('should add a deferrable initially immediate unique constraint', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .addUniqueConstraint(\n                  'some_constraint',\n                  ['varchar_col', 'integer_col'],\n                  (uc) => uc.deferrable().initiallyImmediate(),\n                )\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" add constraint \"some_constraint\" unique (\"varchar_col\", \"integer_col\") deferrable initially immediate',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n          }\n        })\n      }\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'mssql'\n      ) {\n        describe('add check constraint', () => {\n          it('should add a check constraint', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addCheckConstraint('some_constraint', sql`integer_col > 0`)\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" check (integer_col > 0)',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` add constraint `some_constraint` check (integer_col > 0)',\n                parameters: [],\n              },\n              mssql: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" check (integer_col > 0)',\n                parameters: [],\n              },\n              sqlite: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" check (integer_col > 0)',\n                parameters: [],\n              },\n            })\n\n            await builder.execute()\n          })\n        })\n      }\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'mssql'\n      ) {\n        describe('add foreign key constraint', () => {\n          it('should add a foreign key constraint', async () => {\n            await ctx.db.schema\n              .createTable('test2')\n              .addColumn('a', 'integer')\n              .addColumn('b', 'varchar(255)')\n              .addUniqueConstraint('unique_a_b', ['a', 'b'])\n              .execute()\n\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addForeignKeyConstraint(\n                'some_constraint',\n                ['integer_col', 'varchar_col'],\n                'test2',\n                ['a', 'b'],\n              )\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" foreign key (\"integer_col\", \"varchar_col\") references \"test2\" (\"a\", \"b\")',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` add constraint `some_constraint` foreign key (`integer_col`, `varchar_col`) references `test2` (`a`, `b`)',\n                parameters: [],\n              },\n              mssql: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" foreign key (\"integer_col\", \"varchar_col\") references \"test2\" (\"a\", \"b\")',\n                parameters: [],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n\n          it('should add a foreign key constraint with on delete and on update', async () => {\n            await ctx.db.schema\n              .createTable('test2')\n              .addColumn('a', 'integer')\n              .addColumn('b', 'varchar(255)')\n              .addUniqueConstraint('unique_a_b', ['a', 'b'])\n              .execute()\n\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addForeignKeyConstraint(\n                'some_constraint',\n                ['integer_col', 'varchar_col'],\n                'test2',\n                ['a', 'b'],\n              )\n              .onDelete('set null')\n              .onUpdate('cascade')\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" foreign key (\"integer_col\", \"varchar_col\") references \"test2\" (\"a\", \"b\") on delete set null on update cascade',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` add constraint `some_constraint` foreign key (`integer_col`, `varchar_col`) references `test2` (`a`, `b`) on delete set null on update cascade',\n                parameters: [],\n              },\n              mssql: {\n                sql: 'alter table \"test\" add constraint \"some_constraint\" foreign key (\"integer_col\", \"varchar_col\") references \"test2\" (\"a\", \"b\") on delete set null on update cascade',\n                parameters: [],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n        })\n      }\n\n      if (dialect === 'postgres') {\n        it('should add a deferrable initially deferred foreign key constraint', async () => {\n          await ctx.db.schema\n            .createTable('test2')\n            .addColumn('a', 'integer')\n            .addColumn('b', 'varchar(255)')\n            .addUniqueConstraint('unique_a_b', ['a', 'b'])\n            .execute()\n\n          const builder = ctx.db.schema\n            .alterTable('test')\n            .addForeignKeyConstraint(\n              'some_constraint',\n              ['integer_col', 'varchar_col'],\n              'test2',\n              ['a', 'b'],\n              (fk) => fk.deferrable().initiallyDeferred(),\n            )\n\n          testSql(builder, dialect, {\n            postgres: {\n              sql: 'alter table \"test\" add constraint \"some_constraint\" foreign key (\"integer_col\", \"varchar_col\") references \"test2\" (\"a\", \"b\") deferrable initially deferred',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await builder.execute()\n        })\n      }\n\n      if (dialect !== 'sqlite') {\n        describe('drop constraint', () => {\n          it('should drop a foreign key constraint', async () => {\n            await ctx.db.schema.dropTable('test').execute()\n\n            await ctx.db.schema\n              .createTable('test2')\n              .addColumn('id', 'integer', (col) => col.unique())\n              .execute()\n\n            await ctx.db.schema\n              .createTable('test')\n              .addColumn('foreign_key', 'integer')\n              .addForeignKeyConstraint(\n                'foreign_key_constraint',\n                ['foreign_key'],\n                'test2',\n                ['id'],\n              )\n              .execute()\n\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .dropConstraint('foreign_key_constraint')\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" drop constraint \"foreign_key_constraint\"',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` drop constraint `foreign_key_constraint`',\n                parameters: [],\n              },\n              mssql: {\n                sql: 'alter table \"test\" drop constraint \"foreign_key_constraint\"',\n                parameters: [],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n        })\n      }\n\n      if (dialect === 'postgres') {\n        describe('rename constraint', () => {\n          it('should rename a foreign key constraint', async () => {\n            await ctx.db.schema.dropTable('test').execute()\n\n            await ctx.db.schema\n              .createTable('test2')\n              .addColumn('id', 'integer', (col) => col.unique())\n              .execute()\n\n            await ctx.db.schema\n              .createTable('test')\n              .addColumn('foreign_key', 'integer')\n              .addForeignKeyConstraint(\n                'foreign_key_constraint',\n                ['foreign_key'],\n                'test2',\n                ['id'],\n              )\n              .execute()\n\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .renameConstraint(\n                'foreign_key_constraint',\n                'new_foreign_key_constraint',\n              )\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" rename constraint \"foreign_key_constraint\" to \"new_foreign_key_constraint\"',\n                parameters: [],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n        })\n      }\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'mssql'\n      ) {\n        describe('add primary key constraint', async () => {\n          beforeEach(() => {\n            return ctx.db.schema\n              .alterTable('test')\n              .addColumn('decimal_col', 'decimal', (cb) => cb.notNull())\n              .addColumn('smallint_col', sql`smallint`, (cb) => cb.notNull())\n              .execute()\n          })\n\n          afterEach(async () => {\n            if (dialect === 'mssql') {\n              await ctx.db.schema\n                .alterTable('test')\n                .dropConstraint('test_pkey')\n                .execute()\n            }\n\n            await ctx.db.schema\n              .alterTable('test')\n              .dropColumn('decimal_col')\n              .dropColumn('smallint_col')\n              .execute()\n          })\n\n          it('should add a primary key constraint', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addPrimaryKeyConstraint('test_pkey', ['decimal_col'])\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" add constraint \"test_pkey\" primary key (\"decimal_col\")',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` add constraint `test_pkey` primary key (`decimal_col`)',\n                parameters: [],\n              },\n              mssql: {\n                sql: 'alter table \"test\" add constraint \"test_pkey\" primary key (\"decimal_col\")',\n                parameters: [],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n\n          if (dialect === 'postgres') {\n            it('should add a deferrable initially deferred primary key constraint', async () => {\n              const builder = ctx.db.schema\n                .alterTable('test')\n                .addPrimaryKeyConstraint('test_pkey', ['decimal_col'], (pk) =>\n                  pk.deferrable().initiallyDeferred(),\n                )\n\n              testSql(builder, dialect, {\n                postgres: {\n                  sql: 'alter table \"test\" add constraint \"test_pkey\" primary key (\"decimal_col\") deferrable initially deferred',\n                  parameters: [],\n                },\n                mysql: NOT_SUPPORTED,\n                mssql: NOT_SUPPORTED,\n                sqlite: NOT_SUPPORTED,\n              })\n\n              await builder.execute()\n            })\n          }\n\n          it('should add a primary key constraint for multiple columns', async () => {\n            const builder = ctx.db.schema\n              .alterTable('test')\n              .addPrimaryKeyConstraint('test_pkey', [\n                'decimal_col',\n                'smallint_col',\n              ])\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: 'alter table \"test\" add constraint \"test_pkey\" primary key (\"decimal_col\", \"smallint_col\")',\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test` add constraint `test_pkey` primary key (`decimal_col`, `smallint_col`)',\n                parameters: [],\n              },\n              mssql: {\n                sql: 'alter table \"test\" add constraint \"test_pkey\" primary key (\"decimal_col\", \"smallint_col\")',\n                parameters: [],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n        })\n      }\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'mssql'\n      ) {\n        describe('parse schema name', () => {\n          beforeEach(cleanup)\n          afterEach(cleanup)\n\n          it('should parse the schema from table name', async () => {\n            await ctx.db.schema.createSchema('test_schema').execute()\n            await ctx.db.schema\n              .createTable('test_schema.test')\n              .addColumn('id', 'varchar(36)')\n              .execute()\n\n            const builder = ctx.db.schema\n              .alterTable('test_schema.test')\n              .addColumn('second_column', 'text')\n\n            testSql(builder, dialect, {\n              postgres: {\n                sql: `alter table \"test_schema\".\"test\" add column \"second_column\" text`,\n                parameters: [],\n              },\n              mysql: {\n                sql: 'alter table `test_schema`.`test` add column `second_column` text',\n                parameters: [],\n              },\n              mssql: {\n                sql: `alter table \"test_schema\".\"test\" add \"second_column\" text`,\n                parameters: [],\n              },\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await builder.execute()\n          })\n\n          async function cleanup() {\n            await ctx.db.schema\n              .dropTable('test_schema.test')\n              .ifExists()\n              .execute()\n            await ctx.db.schema.dropSchema('test_schema').ifExists().execute()\n          }\n        })\n      }\n\n      it('should alter a table calling query builder functions', async () => {\n        const builder = ctx.db.schema\n          .alterTable('test')\n          .$call((builder) =>\n            builder.addColumn('abc', 'integer', (col) => col.notNull()),\n          )\n\n        testSql(builder, dialect, {\n          postgres: {\n            sql: [`alter table \"test\" add column \"abc\" integer not null`],\n            parameters: [],\n          },\n          mysql: {\n            sql: ['alter table `test` add column `abc` integer not null'],\n            parameters: [],\n          },\n          mssql: {\n            sql: [`alter table \"test\" add \"abc\" integer not null`],\n            parameters: [],\n          },\n          sqlite: {\n            sql: [`alter table \"test\" add column \"abc\" integer not null`],\n            parameters: [],\n          },\n        })\n\n        await builder.execute()\n      })\n\n      if (dialect === 'mysql') {\n        describe('add index', () => {\n          it('should add an index', async () => {\n            const query = ctx.db.schema\n              .alterTable('test')\n              .addIndex('test_integer_col_index')\n              .column('integer_col')\n\n            testSql(query, dialect, {\n              mysql: {\n                sql: 'alter table `test` add index `test_integer_col_index` (`integer_col`)',\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await query.execute()\n          })\n\n          it('should add a unique index', async () => {\n            const query = ctx.db.schema\n              .alterTable('test')\n              .addIndex('test_integer_col_index')\n              .unique()\n              .column('integer_col')\n\n            testSql(query, dialect, {\n              mysql: {\n                sql: 'alter table `test` add unique index `test_integer_col_index` (`integer_col`)',\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await query.execute()\n          })\n\n          it('should add an index for multiple columns', async () => {\n            const query = ctx.db.schema\n              .alterTable('test')\n              .addIndex('test_integer_varchar_col_index')\n              .unique()\n              .columns(['integer_col', 'varchar_col'])\n\n            testSql(query, dialect, {\n              mysql: {\n                sql: 'alter table `test` add unique index `test_integer_varchar_col_index` (`integer_col`, `varchar_col`)',\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await query.execute()\n          })\n\n          it('should add an index for an expression', async () => {\n            const query = ctx.db.schema\n              .alterTable('test')\n              .addIndex('test_varchar_col_index')\n              .expression(sql`(varchar_col < 'Sami')`)\n\n            testSql(query, dialect, {\n              mysql: {\n                sql: \"alter table `test` add index `test_varchar_col_index` ((varchar_col < 'Sami'))\",\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await query.execute()\n          })\n\n          it('should add a sorted index, single column', async () => {\n            const query = ctx.db.schema\n              .alterTable('test')\n              .addIndex('test_integer_col_index')\n              .column('integer_col desc')\n\n            testSql(query, dialect, {\n              mysql: {\n                sql: 'alter table `test` add index `test_integer_col_index` (`integer_col` desc)',\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await query.execute()\n          })\n\n          it('should add a sorted index, multi-column', async () => {\n            const query = ctx.db.schema\n              .alterTable('test')\n              .addIndex('test_integer_varchar_col_index')\n              .columns(['integer_col desc', 'varchar_col desc'])\n\n            testSql(query, dialect, {\n              mysql: {\n                sql: 'alter table `test` add index `test_integer_varchar_col_index` (`integer_col` desc, `varchar_col` desc)',\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await query.execute()\n          })\n        })\n      }\n\n      if (dialect === 'mysql') {\n        describe('drop index', () => {\n          beforeEach(async () => {\n            await ctx.db.schema\n              .alterTable('test')\n              .addIndex('test_integer_col_index')\n              .column('integer_col')\n              .execute()\n          })\n\n          it('should drop an index', async () => {\n            const query = ctx.db.schema\n              .alterTable('test')\n              .dropIndex('test_integer_col_index')\n\n            testSql(query, dialect, {\n              mysql: {\n                sql: 'alter table `test` drop index `test_integer_col_index`',\n                parameters: [],\n              },\n              postgres: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await query.execute()\n          })\n        })\n      }\n    })\n\n    async function dropTestTables(): Promise<void> {\n      await ctx.db.schema.dropTable('test').ifExists().execute()\n      await ctx.db.schema.dropTable('test2').ifExists().execute()\n    }\n\n    async function getColumnMeta(ref: string): Promise<ColumnMetadata> {\n      const [table, column] = ref.split('.')\n      const tables = await ctx.db.introspection.getTables()\n      const tableMeta = tables.find((it) => it.name === table)\n      return tableMeta!.columns.find((it) => it.name === column)!\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/select.test.ts",
    "content": "import { Kysely, PostgresDialect, sql } from '../../../'\nimport { Pool } from 'pg'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  insertPersons,\n  TestContext,\n  testSql,\n  expect,\n  NOT_SUPPORTED,\n  PLUGINS,\n  DIALECT_CONFIGS,\n  Database,\n  POOL_SIZE,\n  DIALECTS,\n  limit,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: select`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertPersons(ctx, [\n        {\n          first_name: 'Jennifer',\n          last_name: 'Aniston',\n          gender: 'female',\n          pets: [\n            {\n              name: 'Catto',\n              species: 'cat',\n              toys: [{ name: 'spool', price: 10 }],\n            },\n          ],\n        },\n        {\n          first_name: 'Arnold',\n          last_name: 'Schwarzenegger',\n          gender: 'male',\n          pets: [{ name: 'Doggo', species: 'dog' }],\n        },\n        {\n          first_name: 'Sylvester',\n          last_name: 'Stallone',\n          gender: 'male',\n          pets: [{ name: 'Hammo', species: 'hamster' }],\n        },\n      ])\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should select all columns', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select * from `person` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select * from \"person\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.containSubset([\n        { first_name: 'Jennifer', last_name: 'Aniston', gender: 'female' },\n      ])\n    })\n\n    it('should select all columns using dynamic table', async () => {\n      const { table } = ctx.db.dynamic\n\n      const query = ctx.db\n        .selectFrom(table('person').as('p'))\n        .selectAll()\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select * from \"person\" as \"p\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select * from `person` as `p` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select * from \"person\" as \"p\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select * from \"person\" as \"p\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.containSubset([\n        { first_name: 'Jennifer', last_name: 'Aniston', gender: 'female' },\n      ])\n    })\n\n    it('should select all columns of a table', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .selectAll('person')\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"person\".* from \"person\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select `person`.* from `person` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select \"person\".* from \"person\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select \"person\".* from \"person\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.containSubset([\n        { first_name: 'Jennifer', last_name: 'Aniston', gender: 'female' },\n      ])\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      it('should select all columns of a table with a schema', async () => {\n        const query = ctx.db\n          .selectFrom('toy_schema.toy')\n          .selectAll('toy_schema.toy')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"toy_schema\".\"toy\".* from \"toy_schema\".\"toy\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select \"toy_schema\".\"toy\".* from \"toy_schema\".\"toy\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n      })\n    }\n\n    it('should select one column', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select('last_name')\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"last_name\" from \"person\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select `last_name` from `person` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select \"last_name\" from \"person\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select \"last_name\" from \"person\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.eql([{ last_name: 'Aniston' }])\n    })\n\n    it('should select one column with an alias', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select('last_name as ln')\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"last_name\" as \"ln\" from \"person\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select `last_name` as `ln` from `person` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select \"last_name\" as \"ln\" from \"person\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select \"last_name\" as \"ln\" from \"person\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.eql([{ ln: 'Aniston' }])\n    })\n\n    it('should select one column with a table name', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select('person.last_name')\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"person\".\"last_name\" from \"person\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select `person`.`last_name` from `person` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select \"person\".\"last_name\" from \"person\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select \"person\".\"last_name\" from \"person\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.eql([{ last_name: 'Aniston' }])\n    })\n\n    it('should select one column with a table name and an alias', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select('person.last_name as ln')\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"person\".\"last_name\" as \"ln\" from \"person\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select `person`.`last_name` as `ln` from `person` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select \"person\".\"last_name\" as \"ln\" from \"person\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select \"person\".\"last_name\" as \"ln\" from \"person\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.eql([{ ln: 'Aniston' }])\n    })\n\n    it('should select one field using a subquery', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select((qb) =>\n          qb\n            .selectFrom('pet')\n            .whereRef('person.id', '=', 'pet.owner_id')\n            .select('name')\n            .as('pet_name'),\n        )\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select (select \"name\" from \"pet\" where \"person\".\"id\" = \"pet\".\"owner_id\") as \"pet_name\" from \"person\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select (select `name` from `pet` where `person`.`id` = `pet`.`owner_id`) as `pet_name` from `person` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select (select \"name\" from \"pet\" where \"person\".\"id\" = \"pet\".\"owner_id\") as \"pet_name\" from \"person\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select (select \"name\" from \"pet\" where \"person\".\"id\" = \"pet\".\"owner_id\") as \"pet_name\" from \"person\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.eql([{ pet_name: 'Catto' }])\n    })\n\n    it('should select the count of jennifers using count', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select((eb) =>\n          eb.fn\n            .count(eb.case().when('first_name', '=', 'Jennifer').then(1).end())\n            .as('num_jennifers'),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select count(case when \"first_name\" = $1 then 1 end) as \"num_jennifers\" from \"person\"',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select count(case when `first_name` = ? then 1 end) as `num_jennifers` from `person`',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select count(case when \"first_name\" = @1 then 1 end) as \"num_jennifers\" from \"person\"',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select count(case when \"first_name\" = ? then 1 end) as \"num_jennifers\" from \"person\"',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const counts = await query.execute()\n\n      expect(counts).to.have.length(1)\n      if (dialect === 'postgres' || dialect === 'mysql') {\n        expect(counts[0]).to.eql({ num_jennifers: '1' })\n      } else {\n        expect(counts[0]).to.eql({ num_jennifers: 1 })\n      }\n    })\n\n    it('should select the count of jennifers using sum', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select((eb) =>\n          eb.fn\n            .sum(\n              eb\n                .case()\n                .when('first_name', '=', 'Jennifer')\n                .then(sql.lit(1))\n                .else(sql.lit(0))\n                .end(),\n            )\n            .as('num_jennifers'),\n        )\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select sum(case when \"first_name\" = $1 then 1 else 0 end) as \"num_jennifers\" from \"person\"',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select sum(case when `first_name` = ? then 1 else 0 end) as `num_jennifers` from `person`',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select sum(case when \"first_name\" = @1 then 1 else 0 end) as \"num_jennifers\" from \"person\"',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select sum(case when \"first_name\" = ? then 1 else 0 end) as \"num_jennifers\" from \"person\"',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const counts = await query.execute()\n\n      expect(counts).to.have.length(1)\n      expect(counts[0]).to.eql({\n        num_jennifers: dialect === 'postgres' || dialect === 'mysql' ? '1' : 1,\n      })\n    })\n\n    // Raw expressions are of course supported on all dialects, but we use an\n    // expression that's only valid on postgres or mssql.\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      it('should select one field using a raw expression', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(\n            sql`concat(${sql.ref(\n              'first_name',\n            )}, ' ', cast(${'Muriel'} as varchar), ' ', ${sql.ref(\n              'last_name',\n            )})`.as('full_name_with_middle_name'),\n          )\n          .where('first_name', '=', 'Jennifer')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select concat(\"first_name\", ' ', cast($1 as varchar), ' ', \"last_name\") as \"full_name_with_middle_name\" from \"person\" where \"first_name\" = $2`,\n            parameters: ['Muriel', 'Jennifer'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: `select concat(\"first_name\", ' ', cast(@1 as varchar), ' ', \"last_name\") as \"full_name_with_middle_name\" from \"person\" where \"first_name\" = @2`,\n            parameters: ['Muriel', 'Jennifer'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(1)\n        expect(persons).to.eql([\n          { full_name_with_middle_name: 'Jennifer Muriel Aniston' },\n        ])\n      })\n    }\n\n    it('should select multiple fields', async () => {\n      const fullName =\n        dialect === 'mysql' || dialect === 'mssql'\n          ? sql`concat(first_name, ' ', last_name)`\n          : sql`first_name || ' ' || last_name`\n\n      const query = ctx.db\n        .selectFrom('person')\n        .select([\n          'first_name',\n          'last_name as ln',\n          'person.gender',\n          'person.first_name as fn',\n          fullName.as('full_name'),\n          (qb) =>\n            qb\n              .selectFrom('pet')\n              .whereRef('person.id', '=', 'owner_id')\n              .select('name')\n              .as('pet_name'),\n        ])\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select \"first_name\", \"last_name\" as \"ln\", \"person\".\"gender\", \"person\".\"first_name\" as \"fn\", first_name || ' ' || last_name as \"full_name\", (select \"name\" from \"pet\" where \"person\".\"id\" = \"owner_id\") as \"pet_name\" from \"person\" where \"first_name\" = $1`,\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: \"select `first_name`, `last_name` as `ln`, `person`.`gender`, `person`.`first_name` as `fn`, concat(first_name, ' ', last_name) as `full_name`, (select `name` from `pet` where `person`.`id` = `owner_id`) as `pet_name` from `person` where `first_name` = ?\",\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: `select \"first_name\", \"last_name\" as \"ln\", \"person\".\"gender\", \"person\".\"first_name\" as \"fn\", concat(first_name, ' ', last_name) as \"full_name\", (select \"name\" from \"pet\" where \"person\".\"id\" = \"owner_id\") as \"pet_name\" from \"person\" where \"first_name\" = @1`,\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: `select \"first_name\", \"last_name\" as \"ln\", \"person\".\"gender\", \"person\".\"first_name\" as \"fn\", first_name || ' ' || last_name as \"full_name\", (select \"name\" from \"pet\" where \"person\".\"id\" = \"owner_id\") as \"pet_name\" from \"person\" where \"first_name\" = ?`,\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.eql([\n        {\n          first_name: 'Jennifer',\n          ln: 'Aniston',\n          gender: 'female',\n          fn: 'Jennifer',\n          full_name: 'Jennifer Aniston',\n          pet_name: 'Catto',\n        },\n      ])\n    })\n\n    it('should select columns from multiple tables in a from clause', async () => {\n      const query = ctx.db\n        .selectFrom(['person', 'pet'])\n        .select(['last_name', 'name as pet_name'])\n        .whereRef('owner_id', '=', 'person.id')\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"last_name\", \"name\" as \"pet_name\" from \"person\", \"pet\" where \"owner_id\" = \"person\".\"id\" and \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select `last_name`, `name` as `pet_name` from `person`, `pet` where `owner_id` = `person`.`id` and `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select \"last_name\", \"name\" as \"pet_name\" from \"person\", \"pet\" where \"owner_id\" = \"person\".\"id\" and \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select \"last_name\", \"name\" as \"pet_name\" from \"person\", \"pet\" where \"owner_id\" = \"person\".\"id\" and \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.eql([{ last_name: 'Aniston', pet_name: 'Catto' }])\n    })\n\n    it('should select columns from multiple expressions in a from clause', async () => {\n      const query = ctx.db\n        .selectFrom([\n          'person',\n          ctx.db.selectFrom('pet').select(['owner_id', 'species']).as('p'),\n          sql<{ one: number }>`(select 1 as one)`.as('o'),\n        ])\n        .select(['last_name', 'species as pet_species', 'one'])\n        .whereRef('p.owner_id', '=', 'person.id')\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"last_name\", \"species\" as \"pet_species\", \"one\" from \"person\", (select \"owner_id\", \"species\" from \"pet\") as \"p\", (select 1 as one) as \"o\" where \"p\".\"owner_id\" = \"person\".\"id\" and \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select `last_name`, `species` as `pet_species`, `one` from `person`, (select `owner_id`, `species` from `pet`) as `p`, (select 1 as one) as `o` where `p`.`owner_id` = `person`.`id` and `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select \"last_name\", \"species\" as \"pet_species\", \"one\" from \"person\", (select \"owner_id\", \"species\" from \"pet\") as \"p\", (select 1 as one) as \"o\" where \"p\".\"owner_id\" = \"person\".\"id\" and \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select \"last_name\", \"species\" as \"pet_species\", \"one\" from \"person\", (select \"owner_id\", \"species\" from \"pet\") as \"p\", (select 1 as one) as \"o\" where \"p\".\"owner_id\" = \"person\".\"id\" and \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    it('should select columns from joined tables', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .innerJoin('pet', 'owner_id', 'person.id')\n        .innerJoin('toy', 'pet_id', 'pet.id')\n        .where('first_name', '=', 'Jennifer')\n        .select(['first_name', 'pet.name as pet_name', 'toy.name as toy_name'])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"first_name\", \"pet\".\"name\" as \"pet_name\", \"toy\".\"name\" as \"toy_name\" from \"person\" inner join \"pet\" on \"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"pet_id\" = \"pet\".\"id\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'select `first_name`, `pet`.`name` as `pet_name`, `toy`.`name` as `toy_name` from `person` inner join `pet` on `owner_id` = `person`.`id` inner join `toy` on `pet_id` = `pet`.`id` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'select \"first_name\", \"pet\".\"name\" as \"pet_name\", \"toy\".\"name\" as \"toy_name\" from \"person\" inner join \"pet\" on \"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"pet_id\" = \"pet\".\"id\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'select \"first_name\", \"pet\".\"name\" as \"pet_name\", \"toy\".\"name\" as \"toy_name\" from \"person\" inner join \"pet\" on \"owner_id\" = \"person\".\"id\" inner join \"toy\" on \"pet_id\" = \"pet\".\"id\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(1)\n      expect(persons).to.eql([\n        { first_name: 'Jennifer', pet_name: 'Catto', toy_name: 'spool' },\n      ])\n    })\n\n    it('should select with distinct', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select('gender')\n        .distinct()\n        .orderBy('gender')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select distinct \"gender\" from \"person\" order by \"gender\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select distinct `gender` from `person` order by `gender`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select distinct \"gender\" from \"person\" order by \"gender\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select distinct \"gender\" from \"person\" order by \"gender\"',\n          parameters: [],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(2)\n      expect(persons).to.eql([{ gender: 'female' }, { gender: 'male' }])\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql') {\n      it('should select a row for update', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('last_name')\n          .where('first_name', '=', 'Jennifer')\n          .forUpdate()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"last_name\" from \"person\" where \"first_name\" = $1 for update',\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: 'select `last_name` from `person` where `first_name` = ? for update',\n            parameters: ['Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(1)\n        expect(persons).to.eql([{ last_name: 'Aniston' }])\n      })\n\n      it('should select a row for update of', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('last_name')\n          .where('first_name', '=', 'Jennifer')\n          .forUpdate('person')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"last_name\" from \"person\" where \"first_name\" = $1 for update of \"person\"',\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: 'select `last_name` from `person` where `first_name` = ? for update of `person`',\n            parameters: ['Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(1)\n        expect(persons).to.eql([{ last_name: 'Aniston' }])\n      })\n\n      it('should select a row for update with skip locked', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('last_name')\n          .where('first_name', '=', 'Jennifer')\n          .forUpdate()\n          .skipLocked()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"last_name\" from \"person\" where \"first_name\" = $1 for update skip locked',\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: 'select `last_name` from `person` where `first_name` = ? for update skip locked',\n            parameters: ['Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(1)\n        expect(persons).to.eql([{ last_name: 'Aniston' }])\n      })\n\n      it('should select a row for update of with skip locked', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('last_name')\n          .where('first_name', '=', 'Jennifer')\n          .forUpdate(['person'])\n          .skipLocked()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"last_name\" from \"person\" where \"first_name\" = $1 for update of \"person\" skip locked',\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: 'select `last_name` from `person` where `first_name` = ? for update of `person` skip locked',\n            parameters: ['Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(1)\n        expect(persons).to.eql([{ last_name: 'Aniston' }])\n      })\n\n      it('should select a row for update with skipLocked called before forUpdate', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('last_name')\n          .where('first_name', '=', 'Jennifer')\n          .skipLocked()\n          .forUpdate()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"last_name\" from \"person\" where \"first_name\" = $1 for update skip locked',\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: 'select `last_name` from `person` where `first_name` = ? for update skip locked',\n            parameters: ['Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(1)\n        expect(persons).to.eql([{ last_name: 'Aniston' }])\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should select with distinct on', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .distinctOn('gender')\n          .orderBy('gender')\n          .orderBy('last_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select distinct on (\"gender\") \"first_name\" from \"person\" order by \"gender\", \"last_name\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(2)\n        expect(persons).to.eql([\n          { first_name: 'Jennifer' },\n          { first_name: 'Arnold' },\n        ])\n      })\n\n      it('should select with distinct on that uses a RawBuilder expression', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(['first_name', 'last_name'])\n          .distinctOn(sql`gender::text`)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select distinct on (gender::text) \"first_name\", \"last_name\" from \"person\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(2)\n        expect(persons).to.eql([\n          { first_name: 'Jennifer', last_name: 'Aniston' },\n          { first_name: 'Arnold', last_name: 'Schwarzenegger' },\n        ])\n      })\n\n      for (const [methods, sql] of [\n        [['forUpdate'], 'for update'],\n        [['forShare'], 'for share'],\n        [['forNoKeyUpdate'], 'for no key update'],\n        [['forKeyShare'], 'for key share'],\n        [['forUpdate', 'noWait'], 'for update nowait'],\n        [['forUpdate', 'skipLocked'], 'for update skip locked'],\n      ] as const) {\n        it(`should support \"${sql}\"`, async () => {\n          let query = ctx.db.selectFrom('person').selectAll()\n\n          for (const method of methods) {\n            query = query[method]()\n          }\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: `select * from \"person\" ${sql}`,\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await query.execute()\n        })\n      }\n    }\n\n    it('should use an aggregate function in a select call', async () => {\n      const { max, min } = ctx.db.fn\n\n      const query = ctx.db\n        .selectFrom('person')\n        .select([\n          max('person.first_name').as('max_first_name'),\n          min('person.first_name').as('min_first_name'),\n        ])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select max(\"person\".\"first_name\") as \"max_first_name\", min(\"person\".\"first_name\") as \"min_first_name\" from \"person\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select max(`person`.`first_name`) as `max_first_name`, min(`person`.`first_name`) as `min_first_name` from `person`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select max(\"person\".\"first_name\") as \"max_first_name\", min(\"person\".\"first_name\") as \"min_first_name\" from \"person\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select max(\"person\".\"first_name\") as \"max_first_name\", min(\"person\".\"first_name\") as \"min_first_name\" from \"person\"',\n          parameters: [],\n        },\n      })\n\n      const { max_first_name, min_first_name } =\n        await query.executeTakeFirstOrThrow()\n\n      expect(min_first_name).to.equal('Arnold')\n      expect(max_first_name).to.equal('Sylvester')\n    })\n\n    it('should use a cast in a select call', async () => {\n      const query = ctx.db\n        .selectFrom('toy')\n        .select((eb) => [\n          eb.cast<number>('price', 'double precision').as('price'),\n        ])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select cast(\"price\" as double precision) as \"price\" from \"toy\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select cast(`price` as double precision) as `price` from `toy`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select cast(\"price\" as double precision) as \"price\" from \"toy\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select cast(\"price\" as double precision) as \"price\" from \"toy\"',\n          parameters: [],\n        },\n      })\n\n      const { price } = await query.executeTakeFirstOrThrow()\n      expect(price).to.equal(10)\n    })\n\n    it('modifyFront should add arbitrary SQL to the front of the query', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select('gender')\n        .modifyFront(sql`distinct`)\n        .orderBy('gender')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select distinct \"gender\" from \"person\" order by \"gender\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select distinct `gender` from `person` order by `gender`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select distinct \"gender\" from \"person\" order by \"gender\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select distinct \"gender\" from \"person\" order by \"gender\"',\n          parameters: [],\n        },\n      })\n\n      const persons = await query.execute()\n\n      expect(persons).to.have.length(2)\n      expect(persons).to.eql([{ gender: 'female' }, { gender: 'male' }])\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql') {\n      it('modifyEnd should add arbitrary SQL to the end of the query', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('last_name')\n          .where('first_name', '=', 'Jennifer')\n          .modifyEnd(sql`for update`)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"last_name\" from \"person\" where \"first_name\" = $1 for update',\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: 'select `last_name` from `person` where `first_name` = ? for update',\n            parameters: ['Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(1)\n        expect(persons).to.eql([{ last_name: 'Aniston' }])\n      })\n    }\n\n    it('should stream results', async () => {\n      const males: unknown[] = []\n\n      const stream = ctx.db\n        .selectFrom('person')\n        .select(['first_name', 'last_name', 'gender'])\n        .where('gender', '=', 'male')\n        .orderBy('first_name')\n        .stream()\n\n      for await (const male of stream) {\n        males.push(male)\n      }\n\n      expect(males).to.have.length(2)\n      expect(males).to.eql([\n        {\n          first_name: 'Arnold',\n          last_name: 'Schwarzenegger',\n          gender: 'male',\n        },\n        {\n          first_name: 'Sylvester',\n          last_name: 'Stallone',\n          gender: 'male',\n        },\n      ])\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      it('should stream results with a specific chunk size', async () => {\n        const males: unknown[] = []\n\n        const stream = ctx.db\n          .selectFrom('person')\n          .select(['first_name', 'last_name', 'gender'])\n          .where('gender', '=', 'male')\n          .orderBy('first_name')\n          .stream(1)\n\n        for await (const male of stream) {\n          males.push(male)\n        }\n\n        expect(males).to.have.length(2)\n        expect(males).to.eql([\n          {\n            first_name: 'Arnold',\n            last_name: 'Schwarzenegger',\n            gender: 'male',\n          },\n          {\n            first_name: 'Sylvester',\n            last_name: 'Stallone',\n            gender: 'male',\n          },\n        ])\n      })\n    }\n\n    it('should release connection on premature async iterator stop', async () => {\n      for (let i = 0; i <= POOL_SIZE + 1; i++) {\n        const stream = ctx.db.selectFrom('person').selectAll().stream()\n\n        for await (const _ of stream) {\n          break\n        }\n      }\n    })\n\n    it('should release connection on premature async iterator stop when using a specific chunk size', async () => {\n      for (let i = 0; i <= POOL_SIZE + 1; i++) {\n        const stream = ctx.db.selectFrom('person').selectAll().stream(1)\n\n        for await (const _ of stream) {\n          break\n        }\n      }\n    })\n\n    if (dialect === 'postgres') {\n      it('should throw an error if the cursor implementation is not provided for the postgres dialect', async () => {\n        const db = new Kysely<Database>({\n          dialect: new PostgresDialect({\n            pool: async () => new Pool(DIALECT_CONFIGS.postgres),\n          }),\n          plugins: PLUGINS,\n        })\n\n        await expect(\n          (async () => {\n            for await (const _ of db\n              .selectFrom('person')\n              .selectAll()\n              .stream()) {\n            }\n          })(),\n        ).to.be.rejectedWith(\n          \"'cursor' is not present in your postgres dialect config. It's required to make streaming work in postgres.\",\n        )\n\n        await db.destroy()\n      })\n    }\n\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') {\n      it('should create a select query with limit and offset', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .limit(2)\n          .offset(1)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select \"first_name\" from \"person\" limit $1 offset $2`,\n            parameters: [2, 1],\n          },\n          mysql: {\n            sql: 'select `first_name` from `person` limit ? offset ?',\n            parameters: [2, 1],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'select \"first_name\" from \"person\" limit ? offset ?',\n            parameters: [2, 1],\n          },\n        })\n\n        const result = await query.execute()\n        expect(result).to.have.length(2)\n      })\n\n      it('should create a select query with literal limit and offset', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .limit(sql.lit(25))\n          .offset(sql.lit(100n))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select \"first_name\" from \"person\" limit 25 offset 100`,\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select `first_name` from `person` limit 25 offset 100',\n            parameters: [],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'select \"first_name\" from \"person\" limit 25 offset 100',\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it('should create a select query with limit and offset expressions', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .limit((eb) => eb.lit(2))\n          .offset((eb) => eb.lit(1))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select \"first_name\" from \"person\" limit 2 offset 1`,\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select `first_name` from `person` limit 2 offset 1',\n            parameters: [],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'select \"first_name\" from \"person\" limit 2 offset 1',\n            parameters: [],\n          },\n        })\n\n        const result = await query.execute()\n        expect(result).to.have.length(2)\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should create a select query with limit null', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .limit(null)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `select \"first_name\" from \"person\" limit $1`,\n            parameters: [null],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n        expect(result).to.have.length(3)\n      })\n    }\n\n    it('should create a select statement without a `from` clause', async () => {\n      const query = ctx.db.selectNoFrom((eb) => [\n        eb\n          .selectFrom('person')\n          .select('first_name')\n          .orderBy('first_name')\n          .$call(limit(1, dialect))\n          .as('person_first_name'),\n      ])\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: `select (select \"first_name\" from \"person\" order by \"first_name\" limit $1) as \"person_first_name\"`,\n          parameters: [1],\n        },\n        mysql: {\n          sql: 'select (select `first_name` from `person` order by `first_name` limit ?) as `person_first_name`',\n          parameters: [1],\n        },\n        mssql: {\n          sql: `select (select top(1) \"first_name\" from \"person\" order by \"first_name\") as \"person_first_name\"`,\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select (select \"first_name\" from \"person\" order by \"first_name\" limit ?) as \"person_first_name\"',\n          parameters: [1],\n        },\n      })\n\n      const result = await query.execute()\n      expect(result).to.have.length(1)\n\n      if (dialect === 'mysql') {\n        // For some weird reason, MySQL returns `one` as a string.\n        expect(result[0]).to.eql({ person_first_name: 'Arnold' })\n      } else {\n        expect(result[0]).to.eql({ person_first_name: 'Arnold' })\n      }\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql') {\n      it('should create a select query with order by, offset and fetch', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .orderBy('first_name')\n          .offset(1)\n          .fetch(2)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"first_name\" from \"person\" order by \"first_name\" offset $1 fetch next $2 rows only',\n            parameters: [1, 2],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select \"first_name\" from \"person\" order by \"first_name\" offset @1 rows fetch next @2 rows only',\n            parameters: [1, 2],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n        expect(result).to.have.length(2)\n      })\n\n      it('should create a select query with order by, offset and fetch only', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .orderBy('first_name')\n          .offset(1)\n          .fetch(2, 'only')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"first_name\" from \"person\" order by \"first_name\" offset $1 fetch next $2 rows only',\n            parameters: [1, 2],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select \"first_name\" from \"person\" order by \"first_name\" offset @1 rows fetch next @2 rows only',\n            parameters: [1, 2],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n        expect(result).to.have.length(2)\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should create a select query with order by, offset and fetch with ties', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .orderBy('first_name')\n          .offset(1)\n          .fetch(2, 'with ties')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"first_name\" from \"person\" order by \"first_name\" offset $1 fetch next $2 rows with ties',\n            parameters: [1, 2],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should create a select query with top', async () => {\n        const query = ctx.db.selectFrom('person').select('first_name').top(2)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select top(2) \"first_name\" from \"person\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should create a select query with top and order by', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .top(2)\n          .orderBy('first_name')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select top(2) \"first_name\" from \"person\" order by \"first_name\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should create a select query with top percent', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .top(50, 'percent')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select top(50) percent \"first_name\" from \"person\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should create a select query with top with ties', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .top(2, 'with ties')\n          .orderBy('first_name')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select top(2) with ties \"first_name\" from \"person\" order by \"first_name\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should create a select query with top percent with ties', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .top(50, 'percent with ties')\n          .orderBy('first_name')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select top(50) percent with ties \"first_name\" from \"person\" order by \"first_name\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/set-operation.test.ts",
    "content": "import {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  insertDefaultDataSet,\n  NOT_SUPPORTED,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: set operations`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should combine two select queries using union', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['id', 'first_name as name'])\n        .union(ctx.db.selectFrom('pet').select(['id', 'name']))\n        .orderBy('name')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `id`, `first_name` as `name` from `person` union select `id`, `name` from `pet` order by `name`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n      })\n\n      const result = await query.execute()\n      expect(result).to.containSubset([\n        { name: 'Arnold' },\n        { name: 'Catto' },\n        { name: 'Doggo' },\n        { name: 'Hammo' },\n        { name: 'Jennifer' },\n        { name: 'Sylvester' },\n      ])\n    })\n\n    it('should combine multiple select queries using union with an array', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['id', 'first_name as name'])\n        .union([\n          ctx.db.selectFrom('pet').select(['id', 'name']),\n          ctx.db.selectFrom('pet').select(['id', 'species as name']),\n        ])\n        .orderBy('name')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" union select \"id\", \"species\" as \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `id`, `first_name` as `name` from `person` union select `id`, `name` from `pet` union select `id`, `species` as `name` from `pet` order by `name`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" union select \"id\", \"species\" as \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" union select \"id\", \"species\" as \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n      })\n\n      const result = await query.execute()\n      expect(result).to.containSubset([\n        { name: 'Arnold' },\n        { name: 'Catto' },\n        { name: 'Doggo' },\n        { name: 'Hammo' },\n        { name: 'Jennifer' },\n        { name: 'Sylvester' },\n        { name: 'cat' },\n        { name: 'dog' },\n        { name: 'hamster' },\n      ])\n    })\n\n    it('should combine multiple select queries using union with a callback returning an array', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['id', 'first_name as name'])\n        .union((eb) => [\n          eb.selectFrom('pet').select(['id', 'name']),\n          eb.selectFrom('pet').select(['id', 'species as name']),\n        ])\n        .orderBy('name')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" union select \"id\", \"species\" as \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `id`, `first_name` as `name` from `person` union select `id`, `name` from `pet` union select `id`, `species` as `name` from `pet` order by `name`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" union select \"id\", \"species\" as \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" union select \"id\", \"species\" as \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n      })\n\n      const result = await query.execute()\n      expect(result).to.containSubset([\n        { name: 'Arnold' },\n        { name: 'Catto' },\n        { name: 'Doggo' },\n        { name: 'Hammo' },\n        { name: 'Jennifer' },\n        { name: 'Sylvester' },\n        { name: 'cat' },\n        { name: 'dog' },\n        { name: 'hamster' },\n      ])\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') {\n      it('should combine three select queries using union and an expression builder', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(['id', 'first_name as name'])\n          .union((eb) =>\n            eb.parens(\n              eb\n                .selectFrom('pet')\n                .select(['id', 'name'])\n                .union(eb.selectFrom('toy').select(['id', 'name'])),\n            ),\n          )\n          .orderBy('name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union (select \"id\", \"name\" from \"pet\" union select \"id\", \"name\" from \"toy\") order by \"name\"',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select `id`, `first_name` as `name` from `person` union (select `id`, `name` from `pet` union select `id`, `name` from `toy`) order by `name`',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union (select \"id\", \"name\" from \"pet\" union select \"id\", \"name\" from \"toy\") order by \"name\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n        expect(result).to.containSubset([\n          { name: 'Arnold' },\n          { name: 'Catto' },\n          { name: 'Doggo' },\n          { name: 'Hammo' },\n          { name: 'Jennifer' },\n          { name: 'Sylvester' },\n        ])\n      })\n    }\n\n    it('should combine two select queries using union all', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['id', 'first_name as name'])\n        .unionAll(ctx.db.selectFrom('pet').select(['id', 'name']))\n        .orderBy('name')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union all select \"id\", \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `id`, `first_name` as `name` from `person` union all select `id`, `name` from `pet` order by `name`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union all select \"id\", \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union all select \"id\", \"name\" from \"pet\" order by \"name\"',\n          parameters: [],\n        },\n      })\n\n      const result = await query.execute()\n      expect(result).to.containSubset([\n        { name: 'Arnold' },\n        { name: 'Catto' },\n        { name: 'Doggo' },\n        { name: 'Hammo' },\n        { name: 'Jennifer' },\n        { name: 'Sylvester' },\n      ])\n    })\n\n    it('should combine three select queries using union and union all', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .select(['id', 'first_name as name'])\n        .unionAll(ctx.db.selectFrom('pet').select(['id', 'name']))\n        .union(ctx.db.selectFrom('toy').select(['id', 'name']))\n        .orderBy('name')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union all select \"id\", \"name\" from \"pet\" union select \"id\", \"name\" from \"toy\" order by \"name\"',\n          parameters: [],\n        },\n        mysql: {\n          sql: 'select `id`, `first_name` as `name` from `person` union all select `id`, `name` from `pet` union select `id`, `name` from `toy` order by `name`',\n          parameters: [],\n        },\n        mssql: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union all select \"id\", \"name\" from \"pet\" union select \"id\", \"name\" from \"toy\" order by \"name\"',\n          parameters: [],\n        },\n        sqlite: {\n          sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union all select \"id\", \"name\" from \"pet\" union select \"id\", \"name\" from \"toy\" order by \"name\"',\n          parameters: [],\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres' || dialect === 'mssql' || dialect === 'sqlite') {\n      it('should combine two select queries using intersect', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(['id', 'first_name as name'])\n          .intersect(ctx.db.selectFrom('pet').select(['id', 'name']))\n          .orderBy('name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" intersect select \"id\", \"name\" from \"pet\" order by \"name\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" intersect select \"id\", \"name\" from \"pet\" order by \"name\"',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" intersect select \"id\", \"name\" from \"pet\" order by \"name\"',\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it('should combine two select queries using except', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(['id', 'first_name as name'])\n          .except(ctx.db.selectFrom('pet').select(['id', 'name']))\n          .orderBy('name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" except select \"id\", \"name\" from \"pet\" order by \"name\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" except select \"id\", \"name\" from \"pet\" order by \"name\"',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" except select \"id\", \"name\" from \"pet\" order by \"name\"',\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n\n      it('should combine three queries using union, union all, intersect and except', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(['id', 'first_name as name'])\n          .union(ctx.db.selectFrom('pet').select(['id', 'name']))\n          .unionAll(ctx.db.selectFrom('toy').select(['id', 'name']))\n          .intersect(ctx.db.selectFrom('pet').select(['id', 'name']))\n          .except(ctx.db.selectFrom('toy').select(['id', 'name']))\n          .orderBy('name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" union all select \"id\", \"name\" from \"toy\" intersect select \"id\", \"name\" from \"pet\" except select \"id\", \"name\" from \"toy\" order by \"name\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" union all select \"id\", \"name\" from \"toy\" intersect select \"id\", \"name\" from \"pet\" except select \"id\", \"name\" from \"toy\" order by \"name\"',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" union select \"id\", \"name\" from \"pet\" union all select \"id\", \"name\" from \"toy\" intersect select \"id\", \"name\" from \"pet\" except select \"id\", \"name\" from \"toy\" order by \"name\"',\n            parameters: [],\n          },\n        })\n\n        await query.execute()\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should combine two select queries using intersect all', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(['id', 'first_name as name'])\n          .intersectAll(ctx.db.selectFrom('pet').select(['id', 'name']))\n          .orderBy('name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" intersect all select \"id\", \"name\" from \"pet\" order by \"name\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should combine two select queries using except all', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .select(['id', 'first_name as name'])\n          .exceptAll(ctx.db.selectFrom('pet').select(['id', 'name']))\n          .orderBy('name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"id\", \"first_name\" as \"name\" from \"person\" except all select \"id\", \"name\" from \"pet\" order by \"name\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/sql-injection.test.ts",
    "content": "import { expect } from 'chai'\nimport { sql } from '../../../'\nimport { destroyTest, DIALECTS, initTest, type TestContext } from './test-setup'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: select`, () => {\n    let ctx: TestContext\n    const identifierWrapper = dialect === 'mysql' ? '`' : '\"'\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should not allow SQL injection in table names', async () => {\n      const query = sql`select * from ${sql.table(\n        `person${identifierWrapper}; drop table person --`,\n      )}`.compile(ctx.db)\n\n      expect(query.sql).to.equal(\n        `select * from ${identifierWrapper}person${identifierWrapper}${identifierWrapper}; drop table person --${identifierWrapper}`,\n      )\n\n      await expect(ctx.db.executeQuery(query)).to.eventually.be.rejected\n      await assertDidNotDropTable(ctx, 'person')\n    })\n\n    it('should not allow SQL injection in column refs', async () => {\n      const query =\n        sql`select ${sql.ref(`first_name${identifierWrapper}; drop table person --`)} from person`.compile(\n          ctx.db,\n        )\n\n      expect(query.sql).to.equal(\n        `select ${identifierWrapper}first_name${identifierWrapper}${identifierWrapper}; drop table person --${identifierWrapper} from person`,\n      )\n\n      await expect(ctx.db.executeQuery(query)).to.eventually.be.rejected\n      await assertDidNotDropTable(ctx, 'person')\n    })\n\n    it('should not allow SQL injection in literals', async () => {\n      const query = ctx.db\n        .selectFrom('person')\n        .where('first_name', '=', sql.lit(`Sylvester'; drop table person --`))\n        .selectAll()\n\n      expect(query.compile().sql).to.equal(\n        `select * from ${identifierWrapper}person${identifierWrapper} where ${identifierWrapper}first_name${identifierWrapper} = 'Sylvester''; drop table person --'`,\n      )\n\n      const results = await ctx.db.executeQuery(query)\n      expect(results.rows).to.have.length(0)\n      await assertDidNotDropTable(ctx, 'person')\n    })\n\n    if (dialect === 'mysql') {\n      it('should not allow SQL injection in $.key JSON paths', async () => {\n        const injection =\n          `first' as ${identifierWrapper}first${identifierWrapper} from ${identifierWrapper}people${identifierWrapper}; drop table ${identifierWrapper}person${identifierWrapper} -- ` as never\n\n        const query = ctx.db\n          .with('people', () =>\n            ctx.db\n              .selectFrom('person')\n              .select(\n                sql<{ first: string }>`json_object('first', first_name)`.as(\n                  'data',\n                ),\n              ),\n          )\n          .selectFrom('people')\n          .select((eb) => eb.ref('data', '->$').key(injection).as('first'))\n\n        expect(query.compile().sql).to.equal(\n          `with ${identifierWrapper}people${identifierWrapper} as (select json_object('first', first_name) as ${identifierWrapper}data${identifierWrapper} from ${identifierWrapper}person${identifierWrapper}) select ${identifierWrapper}data${identifierWrapper}->'$.first'' as ${identifierWrapper}first${identifierWrapper} from ${identifierWrapper}people${identifierWrapper}; drop table ${identifierWrapper}person${identifierWrapper} -- ' as ${identifierWrapper}first${identifierWrapper} from ${identifierWrapper}people${identifierWrapper}`,\n        )\n        await ctx.db.executeQuery(query)\n        await assertDidNotDropTable(ctx, 'person')\n      })\n\n      it('should not allow SQL injection via backslash escape in $.key JSON paths', async () => {\n        const injection =\n          `first\\\\' as ${identifierWrapper}first${identifierWrapper} from ${identifierWrapper}people${identifierWrapper}; drop table ${identifierWrapper}person${identifierWrapper} -- ` as never\n\n        const query = ctx.db\n          .with('people', () =>\n            ctx.db\n              .selectFrom('person')\n              .select(\n                sql<{ first: string }>`json_object('first', first_name)`.as(\n                  'data',\n                ),\n              ),\n          )\n          .selectFrom('people')\n          .select((eb) => eb.ref('data', '->$').key(injection).as('first'))\n\n        expect(query.compile().sql).to.equal(\n          `with ${identifierWrapper}people${identifierWrapper} as (select json_object('first', first_name) as ${identifierWrapper}data${identifierWrapper} from ${identifierWrapper}person${identifierWrapper}) select ${identifierWrapper}data${identifierWrapper}->'$.first\\\\\\\\'' as ${identifierWrapper}first${identifierWrapper} from ${identifierWrapper}people${identifierWrapper}; drop table ${identifierWrapper}person${identifierWrapper} -- ' as ${identifierWrapper}first${identifierWrapper} from ${identifierWrapper}people${identifierWrapper}`,\n        )\n        await ctx.db.executeQuery(query)\n        await assertDidNotDropTable(ctx, 'person')\n      })\n\n      it('should not allow SQL injection via backslash escape in string literals', async () => {\n        const injection = `\\\\'; drop table ${identifierWrapper}person${identifierWrapper}; -- `\n\n        const query = ctx.db\n          .selectFrom('person')\n          .where('first_name', '=', sql.lit(injection))\n          .selectAll()\n\n        expect(query.compile().sql).to.equal(\n          `select * from ${identifierWrapper}person${identifierWrapper} where ${identifierWrapper}first_name${identifierWrapper} = '\\\\\\\\''; drop table ${identifierWrapper}person${identifierWrapper}; -- '`,\n        )\n        await ctx.db.executeQuery(query)\n        await assertDidNotDropTable(ctx, 'person')\n      })\n    }\n  })\n}\n\nasync function assertDidNotDropTable(ctx: TestContext, tableName: string) {\n  const tables = await ctx.db.introspection.getTables()\n\n  expect(tables.some((table) => table.name === tableName)).to.be.true\n}\n"
  },
  {
    "path": "test/node/src/stream.test.ts",
    "content": "import {\n  DIALECTS,\n  Database,\n  TestContext,\n  createTableWithId,\n  destroyTest,\n  expect,\n  initTest,\n} from './test-setup'\nimport { GeneratedAlways, Kysely, sql } from '../../..'\nimport { Request } from 'tedious'\nimport { SinonSandbox, SinonSpy, createSandbox } from 'sinon'\n\nconst CHUNK_SIZE = 10\nconst DIALECT = 'mssql'\nconst ITEM_COUNT = 100\nconst TABLE = 'stream_test'\n\nif (DIALECTS.includes(DIALECT)) {\n  describe(`mssql: stream`, () => {\n    let sandbox: SinonSandbox\n    let pauseSpy: SinonSpy\n    let resumeSpy: SinonSpy\n    let ctx: Omit<TestContext, 'db'> & {\n      db: Kysely<Database & { [TABLE]: { id: GeneratedAlways<number> } }>\n    }\n\n    before(async function () {\n      sandbox = createSandbox()\n      pauseSpy = sandbox.spy(Request.prototype, 'pause')\n      resumeSpy = sandbox.spy(Request.prototype, 'resume')\n\n      ctx = (await initTest(this, DIALECT)) as any\n      try {\n        await ctx.db.schema.dropTable(TABLE).execute()\n      } catch (err) {}\n      await createTableWithId(ctx.db.schema, DIALECT, TABLE).execute()\n      await sql`\n        set identity_insert ${sql.table(TABLE)} on;\n        with cteNums(n) AS (\n          SELECT 1\n          UNION ALL\n          SELECT n + 1\n          FROM cteNums WHERE n < ${sql.lit(ITEM_COUNT)} -- how many times to iterate\n        )\n        INSERT ${sql.table(TABLE)} (id)\n        SELECT * FROM cteNums\n        OPTION (MAXRECURSION ${sql.lit(ITEM_COUNT)});\n        set identity_insert ${sql.table(TABLE)} off\n      `.execute(ctx.db)\n    })\n\n    after(async () => {\n      await ctx.db.schema.dropTable(TABLE).execute()\n      await destroyTest(ctx as any)\n      sandbox.restore()\n    })\n\n    it('should pause/resume the request according to chunk size', async () => {\n      for await (const _ of ctx.db\n        .selectFrom(TABLE)\n        .selectAll()\n        .stream(CHUNK_SIZE));\n\n      const chunks = Math.ceil(ITEM_COUNT / CHUNK_SIZE)\n\n      expect(pauseSpy.callCount).to.equal(chunks)\n      expect(resumeSpy.callCount).to.equal(chunks + 1)\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/test-migrations/migration1.ts",
    "content": "import { Kysely } from '../../../../'\n\nexport async function up(db: Kysely<any>): Promise<void> {\n  await db.schema\n    .createTable('test1')\n    .addColumn('id', 'integer', (col) => col.primaryKey())\n    .execute()\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n  await db.schema.dropTable('test1').execute()\n}\n"
  },
  {
    "path": "test/node/src/test-migrations/migration2.ts",
    "content": "import { Kysely } from '../../../../'\n\nexport async function up(db: Kysely<any>): Promise<void> {\n  await db.schema\n    .createTable('test2')\n    .addColumn('id', 'integer', (col) => col.primaryKey())\n    .addColumn('test1_id', 'integer', (col) => col.references('test1.id'))\n    .execute()\n}\n\n// Down migration is missing on purpose. It's optional.\n"
  },
  {
    "path": "test/node/src/test-setup.ts",
    "content": "import * as chai from 'chai'\nimport chaiAsPromised from 'chai-as-promised'\nimport Cursor from 'pg-cursor'\nimport { Pool, PoolConfig } from 'pg'\nimport { createPool } from 'mysql2'\nimport Database from 'better-sqlite3'\nimport * as Tarn from 'tarn'\nimport * as Tedious from 'tedious'\nimport { PoolOptions } from 'mysql2'\n\nchai.use(chaiAsPromised)\n\nimport {\n  Kysely,\n  KyselyConfig,\n  KyselyPlugin,\n  Compilable,\n  RootOperationNode,\n  PluginTransformQueryArgs,\n  PluginTransformResultArgs,\n  QueryResult,\n  UnknownRow,\n  OperationNodeTransformer,\n  PostgresDialect,\n  MysqlDialect,\n  SchemaModule,\n  InsertResult,\n  SqliteDialect,\n  InsertQueryBuilder,\n  Generated,\n  sql,\n  ColumnType,\n  InsertObject,\n  MssqlDialect,\n  SelectQueryBuilder,\n} from '../../../'\nimport {\n  OrderByDirection,\n  OrderByExpression,\n} from '../../../dist/cjs/parser/order-by-parser'\nimport type { ConnectionConfiguration } from 'tedious'\n\nexport type Gender = 'male' | 'female' | 'other'\nexport type MaritalStatus = 'single' | 'married' | 'divorced' | 'widowed'\nexport type Species = 'dog' | 'cat' | 'hamster'\n\nexport interface Person {\n  id: Generated<number>\n  first_name: string | null\n  middle_name: ColumnType<string | null, string | undefined, string | undefined>\n  last_name: string | null\n  gender: Gender\n  marital_status: MaritalStatus | null\n  children: Generated<number>\n}\n\nexport interface Pet {\n  id: Generated<number>\n  name: string\n  owner_id: number\n  species: Species\n}\n\nexport interface Toy {\n  id: Generated<number>\n  name: string\n  price: number\n  pet_id: number\n}\n\nexport interface Database {\n  person: Person\n  pet: Pet\n  toy: Toy\n  'toy_schema.toy': Toy\n}\n\ninterface PersonInsertParams extends InsertObject<Database, 'person'> {\n  pets?: PetInsertParams[]\n}\n\ninterface PetInsertParams extends Omit<Pet, 'id' | 'owner_id'> {\n  toys?: Omit<Toy, 'id' | 'pet_id'>[]\n}\n\nexport interface TestContext {\n  dialect: BuiltInDialect\n  config: KyselyConfig\n  db: Kysely<Database>\n}\n\nexport type BuiltInDialect = 'postgres' | 'mysql' | 'mssql' | 'sqlite'\nexport type PerDialect<T> = Record<BuiltInDialect, T>\n\nexport const DIALECTS: BuiltInDialect[] = (\n  ['postgres', 'mysql', 'mssql', 'sqlite'] as const\n).filter(\n  (d) =>\n    !process.env.DIALECTS ||\n    process.env.DIALECTS.split(',')\n      .map((it) => it.trim())\n      .includes(d),\n)\n\nconst TEST_INIT_TIMEOUT = 5 * 60 * 1000\n// This can be used as a placeholder for testSql when a query is not\n// supported on some dialect.\nexport const NOT_SUPPORTED = { sql: '', parameters: [] }\n\nexport const PLUGINS: KyselyPlugin[] = []\n\nif (process.env.TEST_TRANSFORMER) {\n  console.log('running tests with a transformer')\n  // Add a noop transformer using a plugin to make sure that the\n  // OperationNodeTransformer base class is implemented correctly\n  // and all nodes and properties get cloned by default.\n  PLUGINS.push(createNoopTransformerPlugin())\n}\n\nexport const POOL_SIZE = 20\n\nconst POSTGRES_CONFIG: PoolConfig = {\n  database: 'kysely_test',\n  host: 'localhost',\n  user: 'kysely',\n  port: 5434,\n  max: POOL_SIZE,\n}\n\nconst MYSQL_CONFIG: PoolOptions = {\n  database: 'kysely_test',\n  host: 'localhost',\n  user: 'kysely',\n  password: 'kysely',\n  port: 3308,\n  // Return big numbers as strings just like pg does.\n  supportBigNumbers: true,\n  bigNumberStrings: true,\n\n  connectionLimit: POOL_SIZE,\n\n  // used in sql injection tests.\n  multipleStatements: true,\n}\n\nconst MSSQL_CONFIG: ConnectionConfiguration = {\n  authentication: {\n    options: {\n      password: 'KyselyTest0',\n      userName: 'sa',\n    },\n    type: 'default',\n  },\n  options: {\n    connectTimeout: 3000,\n    database: 'kysely_test',\n    port: 21433,\n    trustServerCertificate: true,\n  },\n  server: 'localhost',\n}\n\nconst SQLITE_CONFIG = {\n  databasePath: ':memory:',\n}\n\nexport const DIALECT_CONFIGS = {\n  postgres: POSTGRES_CONFIG,\n  mysql: MYSQL_CONFIG,\n  mssql: MSSQL_CONFIG,\n  sqlite: SQLITE_CONFIG,\n}\n\nexport const DB_CONFIGS: PerDialect<KyselyConfig> = {\n  postgres: {\n    dialect: new PostgresDialect({\n      pool: async () => new Pool(DIALECT_CONFIGS.postgres),\n      cursor: Cursor,\n    }),\n    plugins: PLUGINS,\n  },\n\n  mysql: {\n    dialect: new MysqlDialect({\n      pool: async () => createPool(DIALECT_CONFIGS.mysql),\n    }),\n    plugins: PLUGINS,\n  },\n\n  mssql: {\n    dialect: new MssqlDialect({\n      resetConnectionsOnRelease: false,\n      tarn: {\n        options: {\n          max: POOL_SIZE,\n          min: 0,\n          // @ts-expect-error making sure people see the deprecation warning\n          validateConnections: true,\n        },\n        ...Tarn,\n      },\n      tedious: {\n        ...Tedious,\n        connectionFactory: () => new Tedious.Connection(DIALECT_CONFIGS.mssql),\n        // @ts-expect-error making sure people see the deprecation warning\n        resetConnectionOnRelease: true,\n      },\n      validateConnections: false,\n    }),\n    plugins: PLUGINS,\n  },\n\n  sqlite: {\n    dialect: new SqliteDialect({\n      database: async () => new Database(DIALECT_CONFIGS.sqlite.databasePath),\n    }),\n    plugins: PLUGINS,\n  },\n}\n\nexport async function initTest(\n  ctx: Mocha.Context,\n  dialect: BuiltInDialect,\n  overrides?: Omit<KyselyConfig, 'dialect'>,\n): Promise<TestContext> {\n  const config = DB_CONFIGS[dialect]\n\n  ctx.timeout(TEST_INIT_TIMEOUT)\n  const db = await connect({ ...config, ...overrides })\n\n  await createDatabase(db, dialect)\n  return { config, db, dialect }\n}\n\nexport async function destroyTest(ctx: TestContext): Promise<void> {\n  await dropDatabase(ctx.db)\n  await ctx.db.destroy()\n}\n\nexport async function insertPersons(\n  ctx: TestContext,\n  insertPersons: PersonInsertParams[],\n): Promise<void> {\n  for (const insertPerson of insertPersons) {\n    const { pets, ...person } = insertPerson\n\n    const personId = await insert(\n      ctx,\n      ctx.db.insertInto('person').values({ ...person }),\n    )\n\n    for (const insertPet of pets ?? []) {\n      await insertPetForPerson(ctx, personId, insertPet)\n    }\n  }\n}\n\nexport const DEFAULT_DATA_SET: PersonInsertParams[] = [\n  {\n    first_name: 'Jennifer',\n    last_name: 'Aniston',\n    gender: 'female',\n    pets: [{ name: 'Catto', species: 'cat' }],\n    marital_status: 'divorced',\n  },\n  {\n    first_name: 'Arnold',\n    last_name: 'Schwarzenegger',\n    gender: 'male',\n    pets: [{ name: 'Doggo', species: 'dog' }],\n    marital_status: 'divorced',\n  },\n  {\n    first_name: 'Sylvester',\n    last_name: 'Stallone',\n    gender: 'male',\n    pets: [{ name: 'Hammo', species: 'hamster' }],\n    marital_status: 'married',\n  },\n]\n\nexport async function insertDefaultDataSet(ctx: TestContext): Promise<void> {\n  await insertPersons(ctx, DEFAULT_DATA_SET)\n}\n\nexport async function clearDatabase(ctx: TestContext): Promise<void> {\n  await ctx.db.deleteFrom('toy').execute()\n  await ctx.db.deleteFrom('pet').execute()\n  await ctx.db.deleteFrom('person').execute()\n}\n\nexport function testSql(\n  query: Compilable,\n  dialect: BuiltInDialect,\n  expectedPerDialect: PerDialect<{ sql: string | string[]; parameters: any[] }>,\n): void {\n  const expected = expectedPerDialect[dialect]\n  const expectedSql = Array.isArray(expected.sql)\n    ? expected.sql.map((it) => it.trim()).join(' ')\n    : expected.sql\n  const sql = query.compile()\n\n  chai.expect(expectedSql).to.equal(sql.sql)\n  chai.expect(expected.parameters).to.eql(sql.parameters)\n}\n\ntestSql.skip = function (\n  _query: Compilable,\n  _dialect: BuiltInDialect,\n  _expectedPerDialect: PerDialect<{\n    sql: string | string[]\n    parameters: any[]\n  }>,\n) {\n  // noop\n}\n\nasync function createDatabase(\n  db: Kysely<Database>,\n  dialect: BuiltInDialect,\n): Promise<void> {\n  await dropDatabase(db)\n\n  await createTableWithId(db.schema, dialect, 'person')\n    .addColumn('first_name', 'varchar(255)')\n    .addColumn('middle_name', 'varchar(255)')\n    .addColumn('last_name', 'varchar(255)')\n    .addColumn('gender', 'varchar(50)', (col) => col.notNull())\n    .addColumn('marital_status', 'varchar(50)')\n    .addColumn('children', 'integer', (col) => col.notNull().defaultTo(0))\n    .execute()\n\n  await createTableWithId(db.schema, dialect, 'pet', true)\n    .addColumn('name', 'varchar(255)', (col) => col.unique().notNull())\n    .addColumn('owner_id', 'integer', (col) =>\n      col.references('person.id').onDelete('cascade').notNull(),\n    )\n    .addColumn('species', 'varchar(50)', (col) => col.notNull())\n    .execute()\n\n  const createToyTableBase = createTableWithId(db.schema, dialect, 'toy')\n    .addColumn('name', 'varchar(255)', (col) => col.notNull())\n    .addColumn('pet_id', 'integer', (col) => col.references('pet.id').notNull())\n\n  if (dialect === 'postgres') {\n    await createToyTableBase\n      .addColumn('price', 'double precision', (col) => col.notNull())\n      .execute()\n    await sql`COMMENT ON COLUMN toy.price IS 'Price in USD';`.execute(db)\n  }\n\n  if (dialect === 'mssql') {\n    await createToyTableBase\n      .addColumn('price', 'double precision', (col) => col.notNull())\n      .execute()\n    await sql`EXECUTE sp_addextendedproperty N'MS_Description', N'Price in USD', N'SCHEMA', N'dbo', N'TABLE', 'toy', N'COLUMN', N'price'`.execute(\n      db,\n    )\n  }\n\n  if (dialect === 'mysql') {\n    await createToyTableBase\n      .addColumn('price', 'double precision', (col) =>\n        col.notNull().modifyEnd(sql`comment ${sql.lit('Price in USD')}`),\n      )\n      .execute()\n  }\n\n  if (dialect === 'sqlite') {\n    // there is no way to add a comment\n    await createToyTableBase\n      .addColumn('price', 'double precision', (col) => col.notNull())\n      .execute()\n  }\n\n  await db.schema\n    .createIndex('pet_owner_id_index')\n    .on('pet')\n    .column('owner_id')\n    .execute()\n}\n\nexport function createTableWithId(\n  schema: SchemaModule,\n  dialect: BuiltInDialect,\n  tableName: string,\n  implicitIncrement: boolean = false,\n) {\n  const builder = schema.createTable(tableName)\n\n  if (dialect === 'postgres') {\n    return builder.addColumn('id', 'serial', (col) => col.primaryKey())\n  }\n\n  if (dialect === 'mssql') {\n    return builder.addColumn('id', 'integer', (col) =>\n      col.identity().notNull().primaryKey(),\n    )\n  }\n\n  return builder.addColumn('id', 'integer', (col) => {\n    if (implicitIncrement && dialect === 'sqlite') {\n      return col.primaryKey()\n    }\n    return col.autoIncrement().primaryKey()\n  })\n}\n\nasync function connect(config: KyselyConfig): Promise<Kysely<Database>> {\n  for (let i = 0; i < TEST_INIT_TIMEOUT; i += 1000) {\n    let db: Kysely<Database> | undefined\n\n    try {\n      db = new Kysely<Database>(config)\n      await sql`select 1`.execute(db)\n      return db\n    } catch (error) {\n      console.error(error)\n\n      if (db) {\n        await db.destroy().catch((error) => error)\n      }\n\n      console.log(\n        'Waiting for the database to become available. Did you remember to run `docker compose up`?',\n      )\n\n      await sleep(1000)\n    }\n  }\n\n  throw new Error('could not connect to database')\n}\n\nasync function dropDatabase(db: Kysely<Database>): Promise<void> {\n  await db.schema.dropTable('toy').ifExists().execute()\n  await db.schema.dropTable('pet').ifExists().execute()\n  await db.schema.dropTable('person').ifExists().execute()\n}\n\nexport const expect = chai.expect\n\nasync function insertPetForPerson(\n  ctx: TestContext,\n  personId: number,\n  insertPet: PetInsertParams,\n): Promise<void> {\n  const { toys, ...pet } = insertPet\n\n  const petId = await insert(\n    ctx,\n    ctx.db.insertInto('pet').values({ ...pet, owner_id: personId }),\n  )\n\n  for (const toy of toys ?? []) {\n    await insertToysForPet(ctx, petId, toy)\n  }\n}\n\nasync function insertToysForPet(\n  ctx: TestContext,\n  petId: number,\n  toy: Omit<Toy, 'id' | 'pet_id'>,\n): Promise<void> {\n  await ctx.db\n    .insertInto('toy')\n    .values({ ...toy, pet_id: petId })\n    .executeTakeFirst()\n}\n\nexport async function insert<TB extends keyof Database>(\n  ctx: TestContext,\n  qb: InsertQueryBuilder<Database, TB, InsertResult>,\n): Promise<number> {\n  const { dialect } = ctx\n\n  if (dialect === 'postgres' || dialect === 'sqlite') {\n    const { id } = await qb.returning('id').executeTakeFirstOrThrow()\n\n    return id\n  }\n\n  if (dialect === 'mssql') {\n    const { id } = await qb\n      .output('inserted.id' as any)\n      .$castTo<{ id: number }>()\n      .executeTakeFirstOrThrow()\n\n    return id\n  }\n\n  const { insertId } = await qb.executeTakeFirstOrThrow()\n\n  return Number(insertId)\n}\n\nfunction createNoopTransformerPlugin(): KyselyPlugin {\n  const transformer = new OperationNodeTransformer()\n\n  return {\n    transformQuery(args: PluginTransformQueryArgs): RootOperationNode {\n      return transformer.transformNode(args.node, args.queryId)\n    },\n\n    async transformResult(\n      args: PluginTransformResultArgs,\n    ): Promise<QueryResult<UnknownRow>> {\n      return args.result\n    },\n  }\n}\n\nfunction sleep(millis: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, millis))\n}\n\nexport function limit<QB extends SelectQueryBuilder<any, any, any>>(\n  limit: number,\n  dialect: BuiltInDialect,\n): (qb: QB) => QB {\n  return (qb) => {\n    if (dialect === 'mssql') {\n      return qb.top(limit) as QB\n    }\n\n    return qb.limit(limit) as QB\n  }\n}\n\nexport function orderBy<QB extends SelectQueryBuilder<any, any, any>>(\n  orderBy: QB extends SelectQueryBuilder<infer DB, infer TB, infer O>\n    ? OrderByExpression<DB, TB, O>\n    : never,\n  direction: OrderByDirection | undefined,\n  dialect: BuiltInDialect,\n): (qb: QB) => QB {\n  return (qb) => {\n    if (dialect === 'mssql') {\n      return qb.orderBy(\n        orderBy,\n        sql`${sql.raw(direction ? `${direction} ` : '')}${sql.raw(\n          'offset 0 rows',\n        )}`,\n      ) as QB\n    }\n\n    return qb.orderBy(orderBy, direction) as QB\n  }\n}\n"
  },
  {
    "path": "test/node/src/transaction.test.ts",
    "content": "import * as sinon from 'sinon'\nimport { Connection, ISOLATION_LEVEL } from 'tedious'\nimport {\n  CompiledQuery,\n  MssqlDriver,\n  MysqlDriver,\n  PostgresDriver,\n  SqliteDriver,\n  Transaction,\n  TRANSACTION_ACCESS_MODES,\n} from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  expect,\n  Database,\n  insertDefaultDataSet,\n  DIALECTS,\n} from './test-setup.js'\nimport { DatabaseError as PostgresError } from 'pg'\nimport { SqliteError } from 'better-sqlite3'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: transaction`, () => {\n    let ctx: TestContext\n    const executedQueries: CompiledQuery[] = []\n    const sandbox = sinon.createSandbox()\n    let tediousBeginTransactionSpy: sinon.SinonSpy<\n      Parameters<Connection['beginTransaction']>,\n      ReturnType<Connection['beginTransaction']>\n    >\n    let tediousCommitTransactionSpy: sinon.SinonSpy<\n      Parameters<Connection['commitTransaction']>,\n      ReturnType<Connection['commitTransaction']>\n    >\n\n    before(async function () {\n      ctx = await initTest(this, dialect, {\n        log(event) {\n          if (event.level === 'query') {\n            executedQueries.push(event.query)\n          }\n        },\n      })\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n      executedQueries.length = 0\n      tediousBeginTransactionSpy = sandbox.spy(\n        Connection.prototype,\n        'beginTransaction',\n      )\n      tediousCommitTransactionSpy = sandbox.spy(\n        Connection.prototype,\n        'commitTransaction',\n      )\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n      sandbox.restore()\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') {\n      for (const isolationLevel of [\n        'read uncommitted',\n        'read committed',\n        'repeatable read',\n        'serializable',\n        ...(dialect === 'mssql' ? (['snapshot'] as const) : []),\n      ] as const) {\n        it(`should set the transaction isolation level as \"${isolationLevel}\"`, async () => {\n          await ctx.db\n            .transaction()\n            .setIsolationLevel(isolationLevel)\n            .execute(async (trx) => {\n              await trx\n                .insertInto('person')\n                .values({\n                  first_name: 'Foo',\n                  last_name: 'Barson',\n                  gender: 'male',\n                })\n                .execute()\n            })\n\n          if (dialect === 'mssql') {\n            expect(tediousBeginTransactionSpy.calledOnce).to.be.true\n            expect(tediousBeginTransactionSpy.getCall(0).args[1]).to.not.be\n              .undefined\n            expect(tediousBeginTransactionSpy.getCall(0).args[2]).to.equal(\n              ISOLATION_LEVEL[\n                isolationLevel.replace(' ', '_').toUpperCase() as any\n              ],\n            )\n            expect(tediousCommitTransactionSpy.calledOnce).to.be.true\n          }\n\n          expect(\n            executedQueries.map((it) => ({\n              sql: it.sql,\n              parameters: it.parameters,\n            })),\n          ).to.eql(\n            {\n              postgres: [\n                {\n                  sql: `start transaction isolation level ${isolationLevel}`,\n                  parameters: [],\n                },\n                {\n                  sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($1, $2, $3)',\n                  parameters: ['Foo', 'Barson', 'male'],\n                },\n                { sql: 'commit', parameters: [] },\n              ],\n              mysql: [\n                {\n                  sql: `set transaction isolation level ${isolationLevel}`,\n                  parameters: [],\n                },\n                { sql: 'begin', parameters: [] },\n                {\n                  sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)',\n                  parameters: ['Foo', 'Barson', 'male'],\n                },\n                { sql: 'commit', parameters: [] },\n              ],\n              mssql: [\n                {\n                  sql: 'insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values (@1, @2, @3)',\n                  parameters: ['Foo', 'Barson', 'male'],\n                },\n              ],\n            }[dialect],\n          )\n        })\n      }\n    }\n\n    if (dialect === 'postgres' || dialect === 'mysql') {\n      for (const accessMode of TRANSACTION_ACCESS_MODES) {\n        it(`should set the transaction access mode as \"${accessMode}\"`, async () => {\n          await ctx.db\n            .transaction()\n            .setAccessMode(accessMode)\n            .execute(async (trx) => {\n              await trx.selectFrom('person').selectAll().execute()\n            })\n\n          expect(\n            executedQueries.map((it) => ({\n              sql: it.sql,\n              parameters: it.parameters,\n            })),\n          ).to.eql(\n            {\n              postgres: [\n                { sql: `start transaction ${accessMode}`, parameters: [] },\n                { sql: 'select * from \"person\"', parameters: [] },\n                { sql: 'commit', parameters: [] },\n              ],\n              mysql: [\n                { sql: `set transaction ${accessMode}`, parameters: [] },\n                { sql: 'begin', parameters: [] },\n                { sql: 'select * from `person`', parameters: [] },\n                { sql: 'commit', parameters: [] },\n              ],\n            }[dialect],\n          )\n        })\n      }\n    }\n\n    if (dialect === 'postgres') {\n      it('should be able to start a transaction with a single connection', async () => {\n        const result = await ctx.db.connection().execute((db) => {\n          return db.transaction().execute((trx) => {\n            return trx\n              .insertInto('person')\n              .values({\n                first_name: 'Foo',\n                last_name: 'Barson',\n                gender: 'male',\n              })\n              .returning('first_name')\n              .executeTakeFirstOrThrow()\n          })\n        })\n\n        expect(result.first_name).to.equal('Foo')\n      })\n    }\n\n    it('should run multiple transactions in parallel', async () => {\n      const threads = Array.from({ length: 100 }).map((_, index) => ({\n        id: 1000000 + index + 1,\n        fails: Math.random() < 0.5,\n      }))\n\n      const results = await Promise.allSettled(\n        threads.map((thread) => executeThread(thread.id, thread.fails)),\n      )\n\n      for (let i = 0; i < threads.length; ++i) {\n        const [personExists, petExists] = await Promise.all([\n          doesPersonExists(threads[i].id),\n          doesPetExists(threads[i].id),\n        ])\n\n        if (threads[i].fails) {\n          expect(personExists).to.equal(false)\n          expect(petExists).to.equal(false)\n          expect(results[i].status === 'rejected')\n        } else {\n          expect(personExists).to.equal(true)\n          expect(petExists).to.equal(true)\n          expect(results[i].status === 'fulfilled')\n        }\n      }\n\n      async function executeThread(id: number, fails: boolean): Promise<void> {\n        await ctx.db.transaction().execute(async (trx) => {\n          await insertPerson(trx, id)\n          await insertPet(trx, id)\n\n          if (fails) {\n            throw new Error()\n          }\n        })\n      }\n    })\n\n    it('should retain the full stack trace', async () => {\n      try {\n        await ctx.db.transaction().execute(async (trx) => {\n          await trx.selectFrom('person').where('id', 'in', -1).execute()\n        })\n\n        expect.fail('Expected transaction to fail')\n      } catch (error) {\n        if (dialect === 'sqlite') {\n          expect(error).to.be.instanceOf(SqliteError)\n        } else if (dialect === 'postgres') {\n          expect(error).to.be.instanceOf(PostgresError)\n        }\n\n        expect((error as Error).stack).to.include('transaction.test.js')\n      }\n    })\n\n    it('should not attempt to rollback if transaction failed to begin', async () => {\n      const driverProto = {\n        postgres: PostgresDriver,\n        mysql: MysqlDriver,\n        mssql: MssqlDriver,\n        sqlite: SqliteDriver,\n      }[dialect].prototype\n      const beginStub = sandbox.stub(driverProto, 'beginTransaction').throws()\n      const callbackSpy = sandbox.spy()\n      const rollbackSpy = sandbox.spy(driverProto, 'rollbackTransaction')\n\n      await ctx.db\n        .transaction()\n        .execute(async (trx) => {\n          callbackSpy()\n          await trx.selectFrom('person').where('id', 'in', -1).execute()\n        })\n        .catch(() => {})\n\n      expect(beginStub.called, 'begin called').to.be.true\n      beginStub.restore()\n      expect(callbackSpy.notCalled, 'callback not called').to.be.true\n      expect(rollbackSpy.notCalled, 'rollback not called').to.be.true\n    })\n\n    it('should throw an error when trying to execute a query after the transaction has been committed', async () => {\n      let escapedTrx: Transaction<Database> | undefined\n\n      await ctx.db.transaction().execute(async (trx) => {\n        escapedTrx = trx\n\n        await trx\n          .insertInto('person')\n          .values({\n            first_name: 'Key',\n            last_name: 'Selly',\n            gender: 'other',\n          })\n          .execute()\n      })\n\n      await expect(\n        escapedTrx!\n          .insertInto('person')\n          .values({\n            first_name: 'Koi',\n            last_name: 'Slee',\n            gender: 'other',\n          })\n          .execute(),\n      ).to.be.rejectedWith('Transaction is already committed')\n    })\n\n    it('should throw an error when trying to execute a query after the transaction has been rolled back', async () => {\n      let escapedTrx: Transaction<Database> | undefined\n\n      await ctx.db\n        .transaction()\n        .execute(async (trx) => {\n          escapedTrx = trx\n\n          await trx\n            .insertInto('person')\n            .values({\n              first_name: 'Key',\n              last_name: 'Selly',\n              gender: 'other',\n            })\n            .execute()\n\n          throw new Error('rollback')\n        })\n        .catch(() => {})\n\n      await expect(\n        escapedTrx!\n          .insertInto('person')\n          .values({\n            first_name: 'Koi',\n            last_name: 'Slee',\n            gender: 'other',\n          })\n          .execute(),\n      ).to.be.rejectedWith('Transaction is already rolled back')\n    })\n\n    async function insertPet(\n      trx: Transaction<Database>,\n      ownerId: number,\n    ): Promise<void> {\n      await trx\n        .insertInto('pet')\n        .values({\n          name: `Pet of ${ownerId}`,\n          owner_id: ownerId,\n          species: 'cat',\n        })\n        .execute()\n    }\n\n    async function insertPerson(\n      trx: Transaction<Database>,\n      id: number,\n    ): Promise<void> {\n      const query = trx.insertInto('person').values({\n        id: id,\n        first_name: `Person ${id}`,\n        last_name: null,\n        gender: 'other',\n      })\n\n      if (dialect === 'mssql') {\n        const compiledQuery = query.compile()\n\n        await trx.executeQuery(\n          CompiledQuery.raw(\n            `set identity_insert \"person\" on; ${compiledQuery.sql}; set identity_insert \"person\" off;`,\n            [...compiledQuery.parameters],\n          ),\n        )\n      } else {\n        await query.execute()\n      }\n    }\n\n    async function doesPersonExists(id: number): Promise<boolean> {\n      return !!(await ctx.db\n        .selectFrom('person')\n        .select('id')\n        .where('id', '=', id)\n        .where('first_name', '=', `Person ${id}`)\n        .executeTakeFirst())\n    }\n\n    async function doesPetExists(ownerId: number): Promise<boolean> {\n      return !!(await ctx.db\n        .selectFrom('pet')\n        .select('id')\n        .where('owner_id', '=', ownerId)\n        .where('name', '=', `Pet of ${ownerId}`)\n        .executeTakeFirst())\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/update.test.ts",
    "content": "import { UpdateResult, sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  NOT_SUPPORTED,\n  insertDefaultDataSet,\n  DEFAULT_DATA_SET,\n  DIALECTS,\n  limit,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: update`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should update one row', async () => {\n      const query = ctx.db\n        .updateTable('person')\n        .set({ first_name: 'Foo', last_name: 'Barson' })\n        .where('gender', '=', 'female')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'update \"person\" set \"first_name\" = $1, \"last_name\" = $2 where \"gender\" = $3',\n          parameters: ['Foo', 'Barson', 'female'],\n        },\n        mysql: {\n          sql: 'update `person` set `first_name` = ?, `last_name` = ? where `gender` = ?',\n          parameters: ['Foo', 'Barson', 'female'],\n        },\n        mssql: {\n          sql: 'update \"person\" set \"first_name\" = @1, \"last_name\" = @2 where \"gender\" = @3',\n          parameters: ['Foo', 'Barson', 'female'],\n        },\n        sqlite: {\n          sql: 'update \"person\" set \"first_name\" = ?, \"last_name\" = ? where \"gender\" = ?',\n          parameters: ['Foo', 'Barson', 'female'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(UpdateResult)\n      expect(result.numUpdatedRows).to.equal(1n)\n      if (dialect === 'mysql') {\n        expect(result.numChangedRows).to.equal(1n)\n      } else {\n        expect(result.numChangedRows).to.undefined\n      }\n\n      expect(\n        await ctx.db\n          .selectFrom('person')\n          .select(['first_name', 'last_name', 'gender'])\n          .orderBy('first_name')\n          .orderBy('last_name')\n          .execute(),\n      ).to.eql([\n        { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' },\n        { first_name: 'Foo', last_name: 'Barson', gender: 'female' },\n        { first_name: 'Sylvester', last_name: 'Stallone', gender: 'male' },\n      ])\n    })\n\n    it('should update one row using the (key, value) variant of `set` method', async () => {\n      const query = ctx.db\n        .updateTable('person')\n        .set('first_name', 'Foo')\n        .set((eb) => eb.ref('last_name'), 'Barson')\n        .set('gender', (eb) => eb.val('other' as const))\n        .where('gender', '=', 'female')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'update \"person\" set \"first_name\" = $1, \"last_name\" = $2, \"gender\" = $3 where \"gender\" = $4',\n          parameters: ['Foo', 'Barson', 'other', 'female'],\n        },\n        mysql: {\n          sql: 'update `person` set `first_name` = ?, `last_name` = ?, `gender` = ? where `gender` = ?',\n          parameters: ['Foo', 'Barson', 'other', 'female'],\n        },\n        mssql: {\n          sql: 'update \"person\" set \"first_name\" = @1, \"last_name\" = @2, \"gender\" = @3 where \"gender\" = @4',\n          parameters: ['Foo', 'Barson', 'other', 'female'],\n        },\n        sqlite: {\n          sql: 'update \"person\" set \"first_name\" = ?, \"last_name\" = ?, \"gender\" = ? where \"gender\" = ?',\n          parameters: ['Foo', 'Barson', 'other', 'female'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(UpdateResult)\n      expect(result.numUpdatedRows).to.equal(1n)\n      if (dialect === 'mysql') {\n        expect(result.numChangedRows).to.equal(1n)\n      } else {\n        expect(result.numChangedRows).to.undefined\n      }\n\n      expect(\n        await ctx.db\n          .selectFrom('person')\n          .select(['first_name', 'last_name', 'gender'])\n          .orderBy('first_name')\n          .orderBy('last_name')\n          .execute(),\n      ).to.eql([\n        { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' },\n        { first_name: 'Foo', last_name: 'Barson', gender: 'other' },\n        { first_name: 'Sylvester', last_name: 'Stallone', gender: 'male' },\n      ])\n    })\n\n    // mssql doesn't support table aliases in update clause, but it does support this\n    // with update alias set ... from table_name as alias\n    if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') {\n      it('should update one row with table alias', async () => {\n        const query = ctx.db\n          .updateTable('person as p')\n          .set({ first_name: 'Foo', last_name: 'Barson' })\n          .where('p.gender', '=', 'female')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'update \"person\" as \"p\" set \"first_name\" = $1, \"last_name\" = $2 where \"p\".\"gender\" = $3',\n            parameters: ['Foo', 'Barson', 'female'],\n          },\n          mysql: {\n            sql: 'update `person` as `p` set `first_name` = ?, `last_name` = ? where `p`.`gender` = ?',\n            parameters: ['Foo', 'Barson', 'female'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'update \"person\" as \"p\" set \"first_name\" = ?, \"last_name\" = ? where \"p\".\"gender\" = ?',\n            parameters: ['Foo', 'Barson', 'female'],\n          },\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(UpdateResult)\n        expect(result.numUpdatedRows).to.equal(1n)\n        if (dialect === 'mysql') {\n          expect(result.numChangedRows).to.equal(1n)\n        } else {\n          expect(result.numChangedRows).to.undefined\n        }\n\n        expect(\n          await ctx.db\n            .selectFrom('person')\n            .select(['first_name', 'last_name', 'gender'])\n            .orderBy('first_name')\n            .orderBy('last_name')\n            .execute(),\n        ).to.eql([\n          { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' },\n          { first_name: 'Foo', last_name: 'Barson', gender: 'female' },\n          { first_name: 'Sylvester', last_name: 'Stallone', gender: 'male' },\n        ])\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should update one row with table alias in from clause', async () => {\n        const query = ctx.db\n          .updateTable('p' as 'person')\n          .set({ first_name: 'Foo', last_name: 'Barson' })\n          .from('person as p')\n          .where('p.gender', '=', 'female')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'update \"p\" set \"first_name\" = @1, \"last_name\" = @2 from \"person\" as \"p\" where \"p\".\"gender\" = @3',\n            parameters: ['Foo', 'Barson', 'female'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(UpdateResult)\n        expect(result.numUpdatedRows).to.equal(1n)\n        expect(result.numChangedRows).to.undefined\n\n        expect(\n          await ctx.db\n            .selectFrom('person')\n            .select(['first_name', 'last_name', 'gender'])\n            .orderBy('first_name')\n            .orderBy('last_name')\n            .execute(),\n        ).to.eql([\n          { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' },\n          { first_name: 'Foo', last_name: 'Barson', gender: 'female' },\n          { first_name: 'Sylvester', last_name: 'Stallone', gender: 'male' },\n        ])\n      })\n    }\n\n    it('should update one row using a subquery', async () => {\n      const query = ctx.db\n        .updateTable('person')\n        .set((eb) => ({\n          last_name: eb\n            .selectFrom('pet')\n            .select('name')\n            .whereRef('person.id', '=', 'owner_id'),\n        }))\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'update \"person\" set \"last_name\" = (select \"name\" from \"pet\" where \"person\".\"id\" = \"owner_id\") where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'update `person` set `last_name` = (select `name` from `pet` where `person`.`id` = `owner_id`) where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'update \"person\" set \"last_name\" = (select \"name\" from \"pet\" where \"person\".\"id\" = \"owner_id\") where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'update \"person\" set \"last_name\" = (select \"name\" from \"pet\" where \"person\".\"id\" = \"owner_id\") where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(UpdateResult)\n      expect(result.numUpdatedRows).to.equal(1n)\n      if (dialect === 'mysql') {\n        expect(result.numChangedRows).to.equal(1n)\n      } else {\n        expect(result.numChangedRows).to.undefined\n      }\n\n      const person = await ctx.db\n        .selectFrom('person')\n        .selectAll()\n        .where('first_name', '=', 'Jennifer')\n        .executeTakeFirstOrThrow()\n\n      expect(person.last_name).to.equal('Catto')\n    })\n\n    if (dialect === 'postgres') {\n      it('should update one row using an expression', async () => {\n        const query = ctx.db\n          .updateTable('person')\n          .set((eb) => ({\n            first_name: eb('first_name', '||', '2'),\n          }))\n          .where('first_name', '=', 'Jennifer')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'update \"person\" set \"first_name\" = \"first_name\" || $1 where \"first_name\" = $2',\n            parameters: ['2', 'Jennifer'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(UpdateResult)\n        expect(result.numUpdatedRows).to.equal(1n)\n        expect(result.numChangedRows).to.undefined\n\n        const jennifer = await ctx.db\n          .selectFrom('person')\n          .where('first_name', '=', 'Jennifer2')\n          .select('first_name')\n          .executeTakeFirstOrThrow()\n\n        expect(jennifer.first_name).to.equal('Jennifer2')\n      })\n    }\n\n    it('should update one row using a raw expression', async () => {\n      const query = ctx.db\n        .updateTable('person')\n        .set({\n          last_name: sql`${sql.ref('first_name')}`,\n        })\n        .where('first_name', '=', 'Jennifer')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'update \"person\" set \"last_name\" = \"first_name\" where \"first_name\" = $1',\n          parameters: ['Jennifer'],\n        },\n        mysql: {\n          sql: 'update `person` set `last_name` = `first_name` where `first_name` = ?',\n          parameters: ['Jennifer'],\n        },\n        mssql: {\n          sql: 'update \"person\" set \"last_name\" = \"first_name\" where \"first_name\" = @1',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'update \"person\" set \"last_name\" = \"first_name\" where \"first_name\" = ?',\n          parameters: ['Jennifer'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(UpdateResult)\n      expect(result.numUpdatedRows).to.equal(1n)\n      if (dialect === 'mysql') {\n        expect(result.numChangedRows).to.equal(1n)\n      } else {\n        expect(result.numChangedRows).to.undefined\n      }\n\n      const jennifer = await ctx.db\n        .selectFrom('person')\n        .where('first_name', '=', 'Jennifer')\n        .select('last_name')\n        .executeTakeFirstOrThrow()\n\n      expect(jennifer.last_name).to.equal('Jennifer')\n    })\n\n    it('should update one row while ignoring undefined values', async () => {\n      const query = ctx.db\n        .updateTable('person')\n        .set({ id: undefined, first_name: 'Foo', last_name: 'Barson' })\n        .where('gender', '=', 'female')\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'update \"person\" set \"first_name\" = $1, \"last_name\" = $2 where \"gender\" = $3',\n          parameters: ['Foo', 'Barson', 'female'],\n        },\n        mysql: {\n          sql: 'update `person` set `first_name` = ?, `last_name` = ? where `gender` = ?',\n          parameters: ['Foo', 'Barson', 'female'],\n        },\n        mssql: {\n          sql: 'update \"person\" set \"first_name\" = @1, \"last_name\" = @2 where \"gender\" = @3',\n          parameters: ['Foo', 'Barson', 'female'],\n        },\n        sqlite: {\n          sql: 'update \"person\" set \"first_name\" = ?, \"last_name\" = ? where \"gender\" = ?',\n          parameters: ['Foo', 'Barson', 'female'],\n        },\n      })\n\n      const result = await query.executeTakeFirst()\n\n      expect(result).to.be.instanceOf(UpdateResult)\n      expect(result.numUpdatedRows).to.equal(1n)\n      if (dialect === 'mysql') {\n        expect(result.numChangedRows).to.equal(1n)\n      } else {\n        expect(result.numChangedRows).to.undefined\n      }\n\n      const female = await ctx.db\n        .selectFrom('person')\n        .where('gender', '=', 'female')\n        .select(['first_name', 'last_name'])\n        .executeTakeFirstOrThrow()\n\n      expect(female).to.deep.equal({\n        first_name: 'Foo',\n        last_name: 'Barson',\n      })\n    })\n\n    if (dialect === 'postgres' || dialect === 'sqlite') {\n      it('should update some rows and return updated rows when `returning` is used', async () => {\n        const query = ctx.db\n          .updateTable('person')\n          .set({ last_name: 'Barson' })\n          .where('gender', '=', 'male')\n          .returning(['first_name', 'last_name'])\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'update \"person\" set \"last_name\" = $1 where \"gender\" = $2 returning \"first_name\", \"last_name\"',\n            parameters: ['Barson', 'male'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'update \"person\" set \"last_name\" = ? where \"gender\" = ? returning \"first_name\", \"last_name\"',\n            parameters: ['Barson', 'male'],\n          },\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(2)\n        expect(Object.keys(result[0]).sort()).to.eql([\n          'first_name',\n          'last_name',\n        ])\n        expect(result).to.containSubset([\n          { first_name: 'Arnold', last_name: 'Barson' },\n          { first_name: 'Sylvester', last_name: 'Barson' },\n        ])\n      })\n    }\n\n    if (dialect === 'sqlite') {\n      it('should order and limit the amount of updated rows and return', async () => {\n        const query = ctx.db\n          .updateTable('person')\n          .set({ last_name: 'Barson' })\n          .where('gender', '=', 'female')\n          .returning('id')\n          .orderBy('first_name')\n          .limit(1)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'update \"person\" set \"last_name\" = ? where \"gender\" = ? returning \"id\" order by \"first_name\" limit ?',\n            parameters: ['Barson', 'female', 1],\n          },\n        })\n      })\n\n      it('should update all rows, returning some fields of updated rows, and conditionally returning additional fields', async () => {\n        const condition = true\n\n        const query = ctx.db\n          .updateTable('person')\n          .set({ last_name: 'Barson' })\n          .returning('first_name')\n          .$if(condition, (qb) => qb.returning('last_name'))\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result.last_name).to.equal('Barson')\n      })\n\n      it('should update some rows and join a table when `from` is called', async () => {\n        const query = ctx.db\n          .updateTable('person')\n          .from('pet')\n          .set({\n            first_name: (eb) => eb.ref('pet.name'),\n          })\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .where('person.first_name', '=', 'Arnold')\n          .returning('first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'update \"person\" set \"first_name\" = \"pet\".\"name\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\" and \"person\".\"first_name\" = $1 returning \"first_name\"',\n            parameters: ['Arnold'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: {\n            sql: 'update \"person\" set \"first_name\" = \"pet\".\"name\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\" and \"person\".\"first_name\" = ? returning \"first_name\"',\n            parameters: ['Arnold'],\n          },\n        })\n\n        const result = await query.execute()\n\n        expect(result[0].first_name).to.equal('Doggo')\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should update some rows and return joined rows when `returningAll` is used', async () => {\n        const query = ctx.db\n          .updateTable('person')\n          .from('pet')\n          .set({\n            first_name: (eb) => eb.ref('pet.name'),\n          })\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .where('person.first_name', '=', 'Arnold')\n          .returningAll('pet')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'update \"person\" set \"first_name\" = \"pet\".\"name\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\" and \"person\".\"first_name\" = $1 returning \"pet\".*',\n            parameters: ['Arnold'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n        expect(result[0].name).to.equal('Doggo')\n        expect(result[0].species).to.equal('dog')\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should update multiple rows and stream returned results', async () => {\n        const stream = ctx.db\n          .updateTable('person')\n          .set({ last_name: 'Nobody' })\n          .returning(['first_name', 'last_name', 'gender'])\n          .stream()\n\n        const people = []\n\n        for await (const person of stream) {\n          people.push(person)\n        }\n\n        expect(people).to.have.length(DEFAULT_DATA_SET.length)\n        expect(people).to.eql(\n          DEFAULT_DATA_SET.map(({ first_name, gender }) => ({\n            first_name,\n            last_name: 'Nobody',\n            gender,\n          })),\n        )\n      })\n    }\n\n    if (dialect === 'mysql') {\n      it('should update but not change the row', async () => {\n        const query = ctx.db\n          .updateTable('person')\n          .set({\n            first_name: 'Jennifer',\n          })\n          .where('first_name', '=', 'Jennifer')\n\n        await query.execute()\n        const result = await query.executeTakeFirst()\n        expect(result).instanceOf(UpdateResult)\n        expect(result.numUpdatedRows).to.equal(1n)\n        expect(result.numChangedRows).to.equal(0n)\n      })\n\n      it('should order and limit the amount of updated rows', async () => {\n        const query = ctx.db\n          .updateTable('person')\n          .set({ first_name: 'Foo' })\n          .orderBy('first_name')\n          .limit(2)\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: 'update `person` set `first_name` = ? order by `first_name` limit ?',\n            parameters: ['Foo', 2],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.executeTakeFirst()\n\n        expect(result).to.be.instanceOf(UpdateResult)\n        expect(result.numUpdatedRows).to.equal(2n)\n        expect(result.numChangedRows).to.equal(2n)\n\n        const people = await ctx.db\n          .selectFrom('person')\n          .select('first_name')\n          .where('first_name', '=', 'Foo')\n          .execute()\n\n        expect(people).to.have.length(2)\n      })\n\n      it('should update joined table using set(column, value) function', async () => {\n        const query = ctx.db\n          .updateTable(['person', 'pet'])\n          .set('person.first_name', 'Jennifer 2')\n          .set('pet.name', 'Doggo 2')\n          .where('person.first_name', '=', 'Jennifer')\n          .whereRef('person.id', '=', 'pet.owner_id')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: 'update `person`, `pet` set `person`.`first_name` = ?, `pet`.`name` = ? where `person`.`first_name` = ? and `person`.`id` = `pet`.`owner_id`',\n            parameters: ['Jennifer 2', 'Doggo 2', 'Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n\n        const jennifer = await ctx.db\n          .selectFrom('person')\n          .select(['id', 'first_name'])\n          .where('first_name', '=', 'Jennifer 2')\n          .execute()\n\n        const doggo = await ctx.db\n          .selectFrom('pet')\n          .select(['name', 'owner_id'])\n          .where('name', '=', 'Doggo 2')\n          .execute()\n\n        expect(jennifer).to.have.length(1)\n        expect(doggo).to.have.length(1)\n        expect(doggo[0].owner_id).to.equal(jennifer[0].id)\n      })\n\n      it('should update joined aliased table using set(column, value) function and', async () => {\n        const query = ctx.db\n          .updateTable(['person as per', 'pet as p'])\n          .set('per.first_name', 'Jennifer 2')\n          .set('p.name', 'Doggo 2')\n          .where('per.first_name', '=', 'Jennifer')\n          .whereRef('per.id', '=', 'p.owner_id')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: 'update `person` as `per`, `pet` as `p` set `per`.`first_name` = ?, `p`.`name` = ? where `per`.`first_name` = ? and `per`.`id` = `p`.`owner_id`',\n            parameters: ['Jennifer 2', 'Doggo 2', 'Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n\n        const jennifer = await ctx.db\n          .selectFrom('person')\n          .select(['id', 'first_name'])\n          .where('first_name', '=', 'Jennifer 2')\n          .execute()\n\n        const doggo = await ctx.db\n          .selectFrom('pet')\n          .select(['name', 'owner_id'])\n          .where('name', '=', 'Doggo 2')\n          .execute()\n\n        expect(jennifer).to.have.length(1)\n        expect(doggo).to.have.length(1)\n        expect(doggo[0].owner_id).to.equal(jennifer[0].id)\n      })\n\n      it('should join expressions', async () => {\n        const query = ctx.db\n          .updateTable([\n            'person',\n            ctx.db.selectFrom('pet').selectAll().as('pet'),\n          ])\n          .set('person.first_name', 'Jennifer 2')\n          .where('person.first_name', '=', 'Jennifer')\n          .whereRef('person.id', '=', 'pet.owner_id')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: 'update `person`, (select * from `pet`) as `pet` set `person`.`first_name` = ? where `person`.`first_name` = ? and `person`.`id` = `pet`.`owner_id`',\n            parameters: ['Jennifer 2', 'Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should update joined table using set(object) function', async () => {\n        const query = ctx.db\n          .updateTable(['person', 'pet'])\n          .set({ name: 'Doggo 2' })\n          .where('person.first_name', '=', 'Jennifer')\n          .whereRef('person.id', '=', 'pet.owner_id')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: {\n            sql: 'update `person`, `pet` set `name` = ? where `person`.`first_name` = ? and `person`.`id` = `pet`.`owner_id`',\n            parameters: ['Doggo 2', 'Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    it('should create an update query that uses a CTE', async () => {\n      const query = ctx.db\n        .with('jennifer_id', (qb) =>\n          qb\n            .selectFrom('person')\n            .where('first_name', '=', 'Jennifer')\n            .$call(limit(1, dialect))\n            .select('id'),\n        )\n        .updateTable('pet')\n        .set((eb) => ({\n          owner_id: eb.selectFrom('jennifer_id').select('id'),\n        }))\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'with \"jennifer_id\" as (select \"id\" from \"person\" where \"first_name\" = $1 limit $2) update \"pet\" set \"owner_id\" = (select \"id\" from \"jennifer_id\")',\n          parameters: ['Jennifer', 1],\n        },\n        mysql: {\n          sql: 'with `jennifer_id` as (select `id` from `person` where `first_name` = ? limit ?) update `pet` set `owner_id` = (select `id` from `jennifer_id`)',\n          parameters: ['Jennifer', 1],\n        },\n        mssql: {\n          sql: 'with \"jennifer_id\" as (select top(1) \"id\" from \"person\" where \"first_name\" = @1) update \"pet\" set \"owner_id\" = (select \"id\" from \"jennifer_id\")',\n          parameters: ['Jennifer'],\n        },\n        sqlite: {\n          sql: 'with \"jennifer_id\" as (select \"id\" from \"person\" where \"first_name\" = ? limit ?) update \"pet\" set \"owner_id\" = (select \"id\" from \"jennifer_id\")',\n          parameters: ['Jennifer', 1],\n        },\n      })\n\n      await query.execute()\n\n      const jennifer = await ctx.db\n        .selectFrom('person')\n        .where('first_name', '=', 'Jennifer')\n        .select('id')\n        .executeTakeFirstOrThrow()\n\n      const pets = await ctx.db.selectFrom('pet').select('owner_id').execute()\n      expect(pets).to.have.length(3)\n\n      // All pets should now belong to jennifer.\n      for (const pet of pets) {\n        expect(pet.owner_id).to.equal(jennifer.id)\n      }\n    })\n\n    if (dialect === 'postgres') {\n      it('should update using a from clause and a join', async () => {\n        const query = ctx.db\n          .updateTable('pet as p')\n          .from('pet')\n          .whereRef('p.id', '=', 'pet.id')\n          .innerJoin('person', 'person.id', 'pet.owner_id')\n          .set((eb) => ({\n            name: eb.fn.coalesce('person.first_name', eb.val('')),\n          }))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'update \"pet\" as \"p\" set \"name\" = coalesce(\"person\".\"first_name\", $1) from \"pet\" inner join \"person\" on \"person\".\"id\" = \"pet\".\"owner_id\" where \"p\".\"id\" = \"pet\".\"id\"',\n            parameters: [''],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n\n        const pets = await ctx.db\n          .selectFrom('pet')\n          .innerJoin('person', 'person.id', 'pet.owner_id')\n          .select(['pet.name as pet_name', 'person.first_name as person_name'])\n          .execute()\n\n        expect(pets).to.have.length(3)\n        for (const pet of pets) {\n          expect(pet.person_name).to.equal(pet.pet_name)\n        }\n      })\n    }\n\n    if (dialect === 'postgres' || dialect === 'mysql') {\n      it('modifyEnd should add arbitrary SQL to the end of the query', async () => {\n        const query = ctx.db\n          .updateTable('person')\n          .set({\n            gender: 'other',\n          })\n          .where('first_name', '=', 'Jennifer')\n          .modifyEnd(sql.raw('-- this is a comment'))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'update \"person\" set \"gender\" = $1 where \"first_name\" = $2 -- this is a comment',\n            parameters: ['other', 'Jennifer'],\n          },\n          mysql: {\n            sql: 'update `person` set `gender` = ? where `first_name` = ? -- this is a comment',\n            parameters: ['other', 'Jennifer'],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(1)\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should update using a from clause and a join', async () => {\n        const query = ctx.db\n          .updateTable('p' as 'pet')\n          .from('pet as p')\n          .innerJoin('person', 'person.id', 'p.owner_id')\n          .set((eb) => ({\n            name: eb.fn.coalesce('person.first_name', eb.val('')),\n          }))\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'update \"p\" set \"name\" = coalesce(\"person\".\"first_name\", @1) from \"pet\" as \"p\" inner join \"person\" on \"person\".\"id\" = \"p\".\"owner_id\"',\n            parameters: [''],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n\n        const pets = await ctx.db\n          .selectFrom('pet')\n          .innerJoin('person', 'person.id', 'pet.owner_id')\n          .select(['pet.name as pet_name', 'person.first_name as person_name'])\n          .execute()\n\n        expect(pets).to.have.length(3)\n        for (const pet of pets) {\n          expect(pet.person_name).to.equal(pet.pet_name)\n        }\n      })\n\n      it('should update top', async () => {\n        const query = ctx.db\n          .updateTable('pet')\n          .top(1)\n          .set({ name: 'Lucky' })\n          .where('species', '=', 'dog')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'update top(1) \"pet\" set \"name\" = @1 where \"species\" = @2',\n            parameters: ['Lucky', 'dog'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should update top percent', async () => {\n        const query = ctx.db\n          .updateTable('pet')\n          .top(50, 'percent')\n          .set({ name: 'Lucky' })\n          .where('species', '=', 'dog')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'update top(50) percent \"pet\" set \"name\" = @1 where \"species\" = @2',\n            parameters: ['Lucky', 'dog'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    if (dialect === 'mssql') {\n      it('should update some rows and return updated rows when `output` is used', async () => {\n        const query = ctx.db\n          .updateTable('person')\n          .set({ last_name: 'Barson' })\n          .output(['inserted.first_name', 'inserted.last_name'])\n          .where('gender', '=', 'male')\n\n        testSql(query, dialect, {\n          postgres: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'update \"person\" set \"last_name\" = @1 output \"inserted\".\"first_name\", \"inserted\".\"last_name\" where \"gender\" = @2',\n            parameters: ['Barson', 'male'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n\n        expect(result).to.have.length(2)\n        expect(Object.keys(result[0]).sort()).to.eql([\n          'first_name',\n          'last_name',\n        ])\n        expect(result).to.containSubset([\n          { first_name: 'Arnold', last_name: 'Barson' },\n          { first_name: 'Sylvester', last_name: 'Barson' },\n        ])\n      })\n\n      it('should update all rows, returning some fields of updated rows, and conditionally returning additional fields', async () => {\n        const condition = true\n\n        const query = ctx.db\n          .updateTable('person')\n          .set({ last_name: 'Barson' })\n          .output('inserted.first_name')\n          .$if(condition, (qb) => qb.output('inserted.last_name'))\n\n        const result = await query.executeTakeFirstOrThrow()\n\n        expect(result.last_name).to.equal('Barson')\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/where.test.ts",
    "content": "import { sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  insertDefaultDataSet,\n  DIALECTS,\n  NOT_SUPPORTED,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: where`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    describe('where', () => {\n      it('a column name and a primitive value', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where('first_name', '=', 'Arnold')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"first_name\" = $1',\n            parameters: ['Arnold'],\n          },\n          mysql: {\n            sql: 'select * from `person` where `first_name` = ?',\n            parameters: ['Arnold'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where \"first_name\" = @1',\n            parameters: ['Arnold'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where \"first_name\" = ?',\n            parameters: ['Arnold'],\n          },\n        })\n\n        const persons = await query.execute()\n\n        expect(persons).to.have.length(1)\n        expect(persons[0].id).to.be.a('number')\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Arnold',\n            last_name: 'Schwarzenegger',\n            gender: 'male',\n          },\n        ])\n      })\n\n      it('a column name and a null value with `is not` operator', async () => {\n        await ctx.db\n          .updateTable('person')\n          .set({ last_name: null })\n          .where('first_name', '=', 'Jennifer')\n          .execute()\n\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where('last_name', 'is not', null)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"last_name\" is not null',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select * from `person` where `last_name` is not null',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where \"last_name\" is not null',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where \"last_name\" is not null',\n            parameters: [],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(2)\n      })\n\n      it('a column name and a null value with `is` operator', async () => {\n        await ctx.db\n          .updateTable('person')\n          .set({ last_name: null })\n          .where('first_name', '=', 'Jennifer')\n          .execute()\n\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where('last_name', 'is', null)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"last_name\" is null',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select * from `person` where `last_name` is null',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where \"last_name\" is null',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where \"last_name\" is null',\n            parameters: [],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(1)\n        expect(persons[0].first_name).to.equal('Jennifer')\n      })\n\n      it('a dynamic column name and a primitive value', async () => {\n        const { ref } = ctx.db.dynamic\n\n        const columnName: string = 'first_name'\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(ref(columnName), '=', 'Arnold')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"first_name\" = $1',\n            parameters: ['Arnold'],\n          },\n          mysql: {\n            sql: 'select * from `person` where `first_name` = ?',\n            parameters: ['Arnold'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where \"first_name\" = @1',\n            parameters: ['Arnold'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where \"first_name\" = ?',\n            parameters: ['Arnold'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(1)\n        expect(persons[0].id).to.be.a('number')\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Arnold',\n            last_name: 'Schwarzenegger',\n            gender: 'male',\n          },\n        ])\n      })\n\n      it('table.column and a primitive value', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where('person.first_name', '=', 'Arnold')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"person\".\"first_name\" = $1',\n            parameters: ['Arnold'],\n          },\n          mysql: {\n            sql: 'select * from `person` where `person`.`first_name` = ?',\n            parameters: ['Arnold'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where \"person\".\"first_name\" = @1',\n            parameters: ['Arnold'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where \"person\".\"first_name\" = ?',\n            parameters: ['Arnold'],\n          },\n        })\n\n        const person = await query.executeTakeFirst()\n        expect(person).to.containSubset({\n          first_name: 'Arnold',\n          last_name: 'Schwarzenegger',\n          gender: 'male',\n        })\n      })\n\n      it('a raw instance and a primitive value', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(sql`person.first_name`, '=', 'Arnold')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where person.first_name = $1',\n            parameters: ['Arnold'],\n          },\n          mysql: {\n            sql: 'select * from `person` where person.first_name = ?',\n            parameters: ['Arnold'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where person.first_name = @1',\n            parameters: ['Arnold'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where person.first_name = ?',\n            parameters: ['Arnold'],\n          },\n        })\n\n        const person = await query.executeTakeFirst()\n        expect(person!.first_name).to.equal('Arnold')\n      })\n\n      it('a raw instance with bindings and a primitive value', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(sql`${sql.ref('person.first_name')}`, '=', 'Arnold')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"person\".\"first_name\" = $1',\n            parameters: ['Arnold'],\n          },\n          mysql: {\n            sql: 'select * from `person` where `person`.`first_name` = ?',\n            parameters: ['Arnold'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where \"person\".\"first_name\" = @1',\n            parameters: ['Arnold'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where \"person\".\"first_name\" = ?',\n            parameters: ['Arnold'],\n          },\n        })\n\n        const person = await query.executeTakeFirst()\n        expect(person!.first_name).to.equal('Arnold')\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'sqlite'\n      ) {\n        it('a raw instance and a boolean value', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .selectAll()\n            .where(sql`(first_name is null)`, 'is', false)\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'select * from \"person\" where (first_name is null) is false',\n              parameters: [],\n            },\n            mysql: {\n              sql: 'select * from `person` where (first_name is null) is false',\n              parameters: [],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'select * from \"person\" where (first_name is null) is false',\n              parameters: [],\n            },\n          })\n\n          const persons = await query.execute()\n          expect(persons).to.have.length(3)\n        })\n      }\n\n      it('a subquery and a primitive value', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(\n            (eb) =>\n              eb\n                .selectFrom('pet')\n                .select('pet.name')\n                .whereRef('owner_id', '=', 'person.id'),\n            '=',\n            'Catto',\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where (select \"pet\".\"name\" from \"pet\" where \"owner_id\" = \"person\".\"id\") = $1',\n            parameters: ['Catto'],\n          },\n          mysql: {\n            sql: 'select * from `person` where (select `pet`.`name` from `pet` where `owner_id` = `person`.`id`) = ?',\n            parameters: ['Catto'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where (select \"pet\".\"name\" from \"pet\" where \"owner_id\" = \"person\".\"id\") = @1',\n            parameters: ['Catto'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where (select \"pet\".\"name\" from \"pet\" where \"owner_id\" = \"person\".\"id\") = ?',\n            parameters: ['Catto'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(1)\n        expect(persons[0].id).to.be.a('number')\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            last_name: 'Aniston',\n            gender: 'female',\n          },\n        ])\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'sqlite'\n      ) {\n        it('a boolean subquery', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .selectAll()\n            .where((eb) =>\n              eb\n                .selectFrom('pet')\n                .whereRef('owner_id', '=', 'person.id')\n                .select((eb) => eb('pet.name', '=', 'Doggo').as('is_doggo')),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'select * from \"person\" where (select \"pet\".\"name\" = $1 as \"is_doggo\" from \"pet\" where \"owner_id\" = \"person\".\"id\")',\n              parameters: ['Doggo'],\n            },\n            mysql: {\n              sql: 'select * from `person` where (select `pet`.`name` = ? as `is_doggo` from `pet` where `owner_id` = `person`.`id`)',\n              parameters: ['Doggo'],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'select * from \"person\" where (select \"pet\".\"name\" = ? as \"is_doggo\" from \"pet\" where \"owner_id\" = \"person\".\"id\")',\n              parameters: ['Doggo'],\n            },\n          })\n\n          const persons = await query.execute()\n          expect(persons).to.have.length(1)\n          expect(persons[0].id).to.be.a('number')\n          expect(persons).to.containSubset([\n            {\n              first_name: 'Arnold',\n              last_name: 'Schwarzenegger',\n              gender: 'male',\n            },\n          ])\n        })\n      }\n\n      it('a raw instance and a subquery', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(sql<string>`${'Catto'}`, '=', (eb) =>\n            eb\n              .selectFrom('pet')\n              .select('pet.name')\n              .whereRef('owner_id', '=', 'person.id'),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where $1 = (select \"pet\".\"name\" from \"pet\" where \"owner_id\" = \"person\".\"id\")',\n            parameters: ['Catto'],\n          },\n          mysql: {\n            sql: 'select * from `person` where ? = (select `pet`.`name` from `pet` where `owner_id` = `person`.`id`)',\n            parameters: ['Catto'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where @1 = (select \"pet\".\"name\" from \"pet\" where \"owner_id\" = \"person\".\"id\")',\n            parameters: ['Catto'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where ? = (select \"pet\".\"name\" from \"pet\" where \"owner_id\" = \"person\".\"id\")',\n            parameters: ['Catto'],\n          },\n        })\n\n        const person = await query.executeTakeFirst()\n        expect(person).to.containSubset({\n          first_name: 'Jennifer',\n          last_name: 'Aniston',\n          gender: 'female',\n        })\n      })\n\n      it('a column name and a raw instance with a raw operator', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where('first_name', sql`=`, sql<string>`${'Arnold'}`)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"first_name\" = $1',\n            parameters: ['Arnold'],\n          },\n          mysql: {\n            sql: 'select * from `person` where `first_name` = ?',\n            parameters: ['Arnold'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where \"first_name\" = @1',\n            parameters: ['Arnold'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where \"first_name\" = ?',\n            parameters: ['Arnold'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(1)\n        expect(persons[0].id).to.be.a('number')\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Arnold',\n            last_name: 'Schwarzenegger',\n            gender: 'male',\n          },\n        ])\n      })\n\n      it('a `where in` query', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where('first_name', 'in', ['Arnold', 'Jennifer'])\n          .orderBy('first_name', 'desc')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"first_name\" in ($1, $2) order by \"first_name\" desc',\n            parameters: ['Arnold', 'Jennifer'],\n          },\n          mysql: {\n            sql: 'select * from `person` where `first_name` in (?, ?) order by `first_name` desc',\n            parameters: ['Arnold', 'Jennifer'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where \"first_name\" in (@1, @2) order by \"first_name\" desc',\n            parameters: ['Arnold', 'Jennifer'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where \"first_name\" in (?, ?) order by \"first_name\" desc',\n            parameters: ['Arnold', 'Jennifer'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(2)\n        expect(persons[0].first_name).to.equal('Jennifer')\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            last_name: 'Aniston',\n            gender: 'female',\n          },\n          {\n            first_name: 'Arnold',\n            last_name: 'Schwarzenegger',\n            gender: 'male',\n          },\n        ])\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'sqlite'\n      ) {\n        it('a `where in` query with tuples', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .selectAll()\n            .where((eb) =>\n              eb(eb.refTuple('first_name', 'last_name'), 'in', [\n                eb.tuple('Jennifer', 'Aniston'),\n                eb.tuple('Sylvester', 'Stallone'),\n              ]),\n            )\n            .orderBy('first_name asc')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'select * from \"person\" where (\"first_name\", \"last_name\") in (($1, $2), ($3, $4)) order by \"first_name\" asc',\n              parameters: ['Jennifer', 'Aniston', 'Sylvester', 'Stallone'],\n            },\n            mysql: {\n              sql: 'select * from `person` where (`first_name`, `last_name`) in ((?, ?), (?, ?)) order by `first_name` asc',\n              parameters: ['Jennifer', 'Aniston', 'Sylvester', 'Stallone'],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'select * from \"person\" where (\"first_name\", \"last_name\") in ((?, ?), (?, ?)) order by \"first_name\" asc',\n              parameters: ['Jennifer', 'Aniston', 'Sylvester', 'Stallone'],\n            },\n          })\n\n          const persons = await query.execute()\n          expect(persons).to.have.length(2)\n          expect(persons).to.containSubset([\n            {\n              first_name: 'Jennifer',\n              last_name: 'Aniston',\n              gender: 'female',\n            },\n            {\n              first_name: 'Sylvester',\n              last_name: 'Stallone',\n              gender: 'male',\n            },\n          ])\n        })\n\n        it('a `where in` query with tuples and a subquery', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .selectAll()\n            .where((eb) =>\n              eb(\n                eb.refTuple('first_name', 'last_name'),\n                'in',\n                eb\n                  .selectFrom('person as p2')\n                  .select(['p2.first_name', 'p2.last_name'])\n                  .where('first_name', 'in', ['Arnold', 'Sylvester'])\n                  .$asTuple('first_name', 'last_name'),\n              ),\n            )\n            .orderBy('first_name asc')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'select * from \"person\" where (\"first_name\", \"last_name\") in (select \"p2\".\"first_name\", \"p2\".\"last_name\" from \"person\" as \"p2\" where \"first_name\" in ($1, $2)) order by \"first_name\" asc',\n              parameters: ['Arnold', 'Sylvester'],\n            },\n            mysql: {\n              sql: 'select * from `person` where (`first_name`, `last_name`) in (select `p2`.`first_name`, `p2`.`last_name` from `person` as `p2` where `first_name` in (?, ?)) order by `first_name` asc',\n              parameters: ['Arnold', 'Sylvester'],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'select * from \"person\" where (\"first_name\", \"last_name\") in (select \"p2\".\"first_name\", \"p2\".\"last_name\" from \"person\" as \"p2\" where \"first_name\" in (?, ?)) order by \"first_name\" asc',\n              parameters: ['Arnold', 'Sylvester'],\n            },\n          })\n\n          const persons = await query.execute()\n          expect(persons).to.have.length(2)\n          expect(persons).to.containSubset([\n            {\n              first_name: 'Arnold',\n              last_name: 'Schwarzenegger',\n              gender: 'male',\n            },\n            {\n              first_name: 'Sylvester',\n              last_name: 'Stallone',\n              gender: 'male',\n            },\n          ])\n        })\n      }\n\n      it('two where expressions', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where('first_name', '=', 'Arnold')\n          .where('person.last_name', '=', 'Schwarzenegger')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where \"first_name\" = $1 and \"person\".\"last_name\" = $2',\n            parameters: ['Arnold', 'Schwarzenegger'],\n          },\n          mysql: {\n            sql: 'select * from `person` where `first_name` = ? and `person`.`last_name` = ?',\n            parameters: ['Arnold', 'Schwarzenegger'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where \"first_name\" = @1 and \"person\".\"last_name\" = @2',\n            parameters: ['Arnold', 'Schwarzenegger'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where \"first_name\" = ? and \"person\".\"last_name\" = ?',\n            parameters: ['Arnold', 'Schwarzenegger'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(1)\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Arnold',\n            last_name: 'Schwarzenegger',\n            gender: 'male',\n          },\n        ])\n      })\n\n      it('`and where` using the expression builder', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where((eb) =>\n            eb.and([\n              eb('first_name', '=', 'Jennifer'),\n              eb(eb.fn('upper', ['last_name']), '=', 'ANISTON'),\n            ]),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where (\"first_name\" = $1 and upper(\"last_name\") = $2)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          mysql: {\n            sql: 'select * from `person` where (`first_name` = ? and upper(`last_name`) = ?)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where (\"first_name\" = @1 and upper(\"last_name\") = @2)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where (\"first_name\" = ? and upper(\"last_name\") = ?)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(1)\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            last_name: 'Aniston',\n            gender: 'female',\n          },\n        ])\n      })\n\n      it('`and where` using the expression builder and chaining', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where((eb) =>\n            eb('first_name', '=', 'Jennifer').and(\n              eb.fn('upper', ['last_name']),\n              '=',\n              'ANISTON',\n            ),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where (\"first_name\" = $1 and upper(\"last_name\") = $2)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          mysql: {\n            sql: 'select * from `person` where (`first_name` = ? and upper(`last_name`) = ?)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where (\"first_name\" = @1 and upper(\"last_name\") = @2)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where (\"first_name\" = ? and upper(\"last_name\") = ?)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(1)\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            last_name: 'Aniston',\n            gender: 'female',\n          },\n        ])\n      })\n\n      it('`and where` using the expression builder and a filter object', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where((eb) =>\n            eb.and({\n              first_name: 'Jennifer',\n              last_name: eb.fn<string>('upper', ['first_name']),\n            }),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where (\"first_name\" = $1 and \"last_name\" = upper(\"first_name\"))',\n            parameters: ['Jennifer'],\n          },\n          mysql: {\n            sql: 'select * from `person` where (`first_name` = ? and `last_name` = upper(`first_name`))',\n            parameters: ['Jennifer'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where (\"first_name\" = @1 and \"last_name\" = upper(\"first_name\"))',\n            parameters: ['Jennifer'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where (\"first_name\" = ? and \"last_name\" = upper(\"first_name\"))',\n            parameters: ['Jennifer'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(0)\n      })\n\n      it('`or where` using the expression builder', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(({ or, eb }) =>\n            or([\n              eb('first_name', '=', 'Jennifer'),\n              eb(eb.fn('upper', ['last_name']), '=', 'ANISTON'),\n            ]),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where (\"first_name\" = $1 or upper(\"last_name\") = $2)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          mysql: {\n            sql: 'select * from `person` where (`first_name` = ? or upper(`last_name`) = ?)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where (\"first_name\" = @1 or upper(\"last_name\") = @2)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where (\"first_name\" = ? or upper(\"last_name\") = ?)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(1)\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            last_name: 'Aniston',\n            gender: 'female',\n          },\n        ])\n      })\n\n      it('`or where` using the expression builder and chaining', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where((eb) =>\n            eb('first_name', '=', 'Jennifer').or(\n              eb.fn('upper', ['last_name']),\n              '=',\n              'ANISTON',\n            ),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where (\"first_name\" = $1 or upper(\"last_name\") = $2)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          mysql: {\n            sql: 'select * from `person` where (`first_name` = ? or upper(`last_name`) = ?)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where (\"first_name\" = @1 or upper(\"last_name\") = @2)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where (\"first_name\" = ? or upper(\"last_name\") = ?)',\n            parameters: ['Jennifer', 'ANISTON'],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(1)\n        expect(persons).to.containSubset([\n          {\n            first_name: 'Jennifer',\n            last_name: 'Aniston',\n            gender: 'female',\n          },\n        ])\n      })\n\n      it('subquery exists', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(({ exists, selectFrom, lit }) =>\n            exists(\n              selectFrom('pet')\n                .select(lit(1).as('exists'))\n                .whereRef('pet.owner_id', '=', 'person.id'),\n            ),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where exists (select 1 as \"exists\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\")',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select * from `person` where exists (select 1 as `exists` from `pet` where `pet`.`owner_id` = `person`.`id`)',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where exists (select 1 as \"exists\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\")',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where exists (select 1 as \"exists\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\")',\n            parameters: [],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(3)\n      })\n\n      it('subquery not exists', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(({ not, exists, selectFrom }) =>\n            not(\n              exists(\n                selectFrom('pet')\n                  .select('pet.id')\n                  .whereRef('pet.owner_id', '=', 'person.id'),\n              ),\n            ),\n          )\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where not exists (select \"pet\".\"id\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\")',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select * from `person` where not exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id`)',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where not exists (select \"pet\".\"id\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\")',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where not exists (select \"pet\".\"id\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\")',\n            parameters: [],\n          },\n        })\n\n        const persons = await query.execute()\n        expect(persons).to.have.length(0)\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'sqlite'\n      ) {\n        it('case expression', async () => {\n          const query = ctx.db\n            .selectFrom('person')\n            .selectAll()\n            .where((eb) =>\n              eb\n                .case()\n                .when('first_name', '=', 'Jennifer')\n                .then(sql.lit(true))\n                .else(sql.lit(false))\n                .end(),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'select * from \"person\" where case when \"first_name\" = $1 then true else false end',\n              parameters: ['Jennifer'],\n            },\n            mysql: {\n              sql: 'select * from `person` where case when `first_name` = ? then true else false end',\n              parameters: ['Jennifer'],\n            },\n            mssql: NOT_SUPPORTED,\n            sqlite: {\n              sql: 'select * from \"person\" where case when \"first_name\" = ? then true else false end',\n              parameters: ['Jennifer'],\n            },\n          })\n\n          const persons = await query.execute()\n          expect(persons).to.have.length(1)\n        })\n      }\n\n      it('single raw instance', async () => {\n        const query = ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .where(sql<boolean>`first_name between ${'Arnold'} and ${'Jennifer'}`)\n          .where(sql<boolean>`last_name between ${'A'} and ${'Z'}`)\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\" where first_name between $1 and $2 and last_name between $3 and $4',\n            parameters: ['Arnold', 'Jennifer', 'A', 'Z'],\n          },\n          mysql: {\n            sql: 'select * from `person` where first_name between ? and ? and last_name between ? and ?',\n            parameters: ['Arnold', 'Jennifer', 'A', 'Z'],\n          },\n          mssql: {\n            sql: 'select * from \"person\" where first_name between @1 and @2 and last_name between @3 and @4',\n            parameters: ['Arnold', 'Jennifer', 'A', 'Z'],\n          },\n          sqlite: {\n            sql: 'select * from \"person\" where first_name between ? and ? and last_name between ? and ?',\n            parameters: ['Arnold', 'Jennifer', 'A', 'Z'],\n          },\n        })\n\n        await query.execute()\n      })\n\n      if (\n        dialect === 'postgres' ||\n        dialect === 'mysql' ||\n        dialect === 'mssql'\n      ) {\n        it('subquery inside `any` operator', async () => {\n          await ctx.db\n            .insertInto('pet')\n            .values((eb) => ({\n              name: 'Cat Stevens',\n              species: 'cat',\n              owner_id: eb\n                .selectFrom('person')\n                .select('id')\n                .where('first_name', '=', 'Jennifer'),\n            }))\n            .execute()\n\n          const query = ctx.db\n            .selectFrom('person')\n            .select('first_name')\n            .where((eb) =>\n              eb(\n                eb.val('Cat Stevens'),\n                '=',\n                eb.fn.any(\n                  eb\n                    .selectFrom('pet')\n                    .whereRef('pet.owner_id', '=', 'person.id')\n                    .select('name'),\n                ),\n              ),\n            )\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'select \"first_name\" from \"person\" where $1 = any((select \"name\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\"))',\n              parameters: ['Cat Stevens'],\n            },\n            mysql: {\n              sql: 'select `first_name` from `person` where ? = any((select `name` from `pet` where `pet`.`owner_id` = `person`.`id`))',\n              parameters: ['Cat Stevens'],\n            },\n            mssql: {\n              sql: 'select \"first_name\" from \"person\" where @1 = any((select \"name\" from \"pet\" where \"pet\".\"owner_id\" = \"person\".\"id\"))',\n              parameters: ['Cat Stevens'],\n            },\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.execute()\n          expect(result).to.have.length(1)\n          expect(result[0]).to.eql({ first_name: 'Jennifer' })\n        })\n      }\n    })\n\n    describe('whereRef', () => {\n      it('should compare two columns', async () => {\n        const query = ctx.db\n          .selectFrom(['person', 'pet'])\n          .selectAll()\n          .whereRef('person.id', '=', 'pet.id')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"person\", \"pet\" where \"person\".\"id\" = \"pet\".\"id\"',\n            parameters: [],\n          },\n          mysql: {\n            sql: 'select * from `person`, `pet` where `person`.`id` = `pet`.`id`',\n            parameters: [],\n          },\n          mssql: {\n            sql: 'select * from \"person\", \"pet\" where \"person\".\"id\" = \"pet\".\"id\"',\n            parameters: [],\n          },\n          sqlite: {\n            sql: 'select * from \"person\", \"pet\" where \"person\".\"id\" = \"pet\".\"id\"',\n            parameters: [],\n          },\n        })\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/node/src/with-schema.test.ts",
    "content": "import type { Kysely } from '../../..'\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  type TestContext,\n  testSql,\n  NOT_SUPPORTED,\n  createTableWithId,\n  DIALECTS,\n  insert,\n  limit,\n  type Database,\n  type Pet,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS.filter(\n  (dialect) => dialect === 'postgres' || dialect === 'mssql',\n)) {\n  describe(`${dialect}: with schema`, () => {\n    let ctx: Omit<TestContext, 'db'> & {\n      db: Kysely<\n        Database & {\n          pet_staging: Pet\n        }\n      >\n    }\n\n    before(async function () {\n      ctx = (await initTest(this, dialect)) as never\n      await dropTables()\n      await createTables()\n    })\n\n    beforeEach(async () => {\n      const personId = await insert(\n        ctx as never,\n        ctx.db.insertInto('person').values({\n          first_name: 'Foo',\n          last_name: 'Bar',\n          gender: 'other',\n        }),\n      )\n\n      await ctx.db\n        .withSchema('mammals')\n        .insertInto('pet')\n        .values({\n          name: 'Catto',\n          owner_id: personId,\n          species: 'cat',\n        })\n        .execute()\n    })\n\n    afterEach(async () => {\n      await ctx.db.withSchema('mammals').deleteFrom('pet').execute()\n      await clearDatabase(ctx as never)\n    })\n\n    after(async () => {\n      await dropTables()\n      await destroyTest(ctx as never)\n    })\n\n    describe('select from', () => {\n      it('should add schema', async () => {\n        const query = ctx.db.withSchema('mammals').selectFrom('pet').selectAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"mammals\".\"pet\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select * from \"mammals\".\"pet\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should add schema for joins', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .selectFrom('pet as p')\n          .leftJoin('pet', 'pet.id', 'p.id')\n          .selectAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"mammals\".\"pet\" as \"p\" left join \"mammals\".\"pet\" on \"mammals\".\"pet\".\"id\" = \"p\".\"id\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select * from \"mammals\".\"pet\" as \"p\" left join \"mammals\".\"pet\" on \"mammals\".\"pet\".\"id\" = \"p\".\"id\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should add schema for aliased joins', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .selectFrom('pet as p1')\n          .leftJoin('pet as p2', 'p1.id', 'p2.id')\n          .selectAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select * from \"mammals\".\"pet\" as \"p1\" left join \"mammals\".\"pet\" as \"p2\" on \"p1\".\"id\" = \"p2\".\"id\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select * from \"mammals\".\"pet\" as \"p1\" left join \"mammals\".\"pet\" as \"p2\" on \"p1\".\"id\" = \"p2\".\"id\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should not add schema for aliases', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .selectFrom('pet as p')\n          .select('p.name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'select \"p\".\"name\" from \"mammals\".\"pet\" as \"p\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'select \"p\".\"name\" from \"mammals\".\"pet\" as \"p\"',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should add schema for subqueries', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .selectFrom('pet')\n          .select([\n            'pet.name',\n            (qb) =>\n              qb\n                .selectFrom('pet as p')\n                .select('name')\n                .whereRef('p.id', '=', 'pet.id')\n                .as('p_name'),\n          ])\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'select \"mammals\".\"pet\".\"name\",',\n              '(select \"name\" from \"mammals\".\"pet\" as \"p\" where \"p\".\"id\" = \"mammals\".\"pet\".\"id\") as \"p_name\"',\n              'from \"mammals\".\"pet\"',\n            ],\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: [\n              'select \"mammals\".\"pet\".\"name\",',\n              '(select \"name\" from \"mammals\".\"pet\" as \"p\" where \"p\".\"id\" = \"mammals\".\"pet\".\"id\") as \"p_name\"',\n              'from \"mammals\".\"pet\"',\n            ],\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('subqueries should use their own schema if specified', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .selectFrom('pet')\n          .select([\n            'pet.name',\n            (qb) =>\n              qb\n                .withSchema(dialect === 'postgres' ? 'public' : 'dbo')\n                .selectFrom('person')\n                .select('first_name')\n                .whereRef('pet.owner_id', '=', 'person.id')\n                .as('owner_first_name'),\n          ])\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: [\n              'select \"mammals\".\"pet\".\"name\",',\n              '(select \"first_name\" from \"public\".\"person\" where \"mammals\".\"pet\".\"owner_id\" = \"public\".\"person\".\"id\") as \"owner_first_name\"',\n              'from \"mammals\".\"pet\"',\n            ],\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: [\n              'select \"mammals\".\"pet\".\"name\",',\n              '(select \"first_name\" from \"dbo\".\"person\" where \"mammals\".\"pet\".\"owner_id\" = \"dbo\".\"person\".\"id\") as \"owner_first_name\"',\n              'from \"mammals\".\"pet\"',\n            ],\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      if (dialect === 'postgres') {\n        it('should not add schema for json_agg parameters', async () => {\n          const query = ctx.db\n            .withSchema('mammals')\n            .selectFrom('pet')\n            .select((eb) => [\n              eb.fn.jsonAgg('pet').as('one'),\n              eb.fn.jsonAgg(eb.table('pet')).as('two'),\n              eb.fn.jsonAgg('pet').orderBy('pet.name', 'desc').as('three'),\n            ])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'select json_agg(\"pet\") as \"one\", json_agg(\"pet\") as \"two\", json_agg(\"pet\" order by \"mammals\".\"pet\".\"name\" desc) as \"three\" from \"mammals\".\"pet\"',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await query.execute()\n        })\n\n        it('should not add schema for to_json parameters', async () => {\n          const query = ctx.db\n            .withSchema('mammals')\n            .selectFrom('pet')\n            .select((eb) => [\n              eb.fn.toJson('pet').as('one'),\n              eb.fn.toJson(eb.table('pet')).as('two'),\n            ])\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'select to_json(\"pet\") as \"one\", to_json(\"pet\") as \"two\" from \"mammals\".\"pet\"',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await query.execute()\n        })\n\n        for (const [selectModifierFn, clause] of [\n          ['forUpdate', 'for update'],\n          ['forShare', 'for share'],\n          ['forKeyShare', 'for key share'],\n          ['forNoKeyUpdate', 'for no key update'],\n        ] as const) {\n          it(`should not add schema to ${clause} tables`, async () => {\n            const query = ctx.db\n              .withSchema('mammals')\n              .selectFrom('pet')\n              .selectAll()\n              [selectModifierFn]('pet')\n              .skipLocked()\n\n            testSql(query, dialect, {\n              postgres: {\n                sql: `select * from \"mammals\".\"pet\" ${clause} of \"pet\" skip locked`,\n                parameters: [],\n              },\n              mysql: NOT_SUPPORTED,\n              mssql: NOT_SUPPORTED,\n              sqlite: NOT_SUPPORTED,\n            })\n\n            await query.execute()\n          })\n        }\n      }\n    })\n\n    describe('insert into', () => {\n      it('should add schema', async () => {\n        const [anyPerson] = await ctx.db\n          .selectFrom('person')\n          .selectAll()\n          .$call(limit(1, dialect))\n          .execute()\n\n        const query = ctx.db\n          .withSchema('mammals')\n          .insertInto('pet')\n          .values({\n            name: 'Doggo',\n            species: 'dog',\n            owner_id: anyPerson.id,\n          })\n          .$call((qb) => (dialect === 'postgres' ? qb.returning('pet.id') : qb))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'insert into \"mammals\".\"pet\" (\"name\", \"species\", \"owner_id\") values ($1, $2, $3) returning \"mammals\".\"pet\".\"id\"',\n            parameters: ['Doggo', 'dog', anyPerson.id],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'insert into \"mammals\".\"pet\" (\"name\", \"species\", \"owner_id\") values (@1, @2, @3)',\n            parameters: ['Doggo', 'dog', anyPerson.id],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    })\n\n    describe('delete from', () => {\n      it('should add schema', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .deleteFrom('pet')\n          .where('pet.name', '=', 'Doggo')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'delete from \"mammals\".\"pet\" where \"mammals\".\"pet\".\"name\" = $1',\n            parameters: ['Doggo'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'delete from \"mammals\".\"pet\" where \"mammals\".\"pet\".\"name\" = @1',\n            parameters: ['Doggo'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      if (dialect === 'postgres') {\n        it('should also add schema to using clause', async () => {\n          const query = ctx.db\n            .withSchema('mammals')\n            .deleteFrom('pet')\n            .using('pet_staging')\n            .whereRef('pet.id', '=', 'pet_staging.id')\n            .where('pet.name', '=', 'Doggo')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'delete from \"mammals\".\"pet\" using \"mammals\".\"pet_staging\" where \"mammals\".\"pet\".\"id\" = \"mammals\".\"pet_staging\".\"id\" and \"mammals\".\"pet\".\"name\" = $1',\n              parameters: ['Doggo'],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await query.execute()\n        })\n      }\n    })\n\n    describe('update', () => {\n      it('should add schema', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .updateTable('pet')\n          .where('pet.name', '=', 'Doggo')\n          .set({ species: 'cat' })\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'update \"mammals\".\"pet\" set \"species\" = $1 where \"mammals\".\"pet\".\"name\" = $2',\n            parameters: ['cat', 'Doggo'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'update \"mammals\".\"pet\" set \"species\" = @1 where \"mammals\".\"pet\".\"name\" = @2',\n            parameters: ['cat', 'Doggo'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    })\n\n    describe('merge into', () => {\n      it('should add schema', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .mergeInto('pet as target')\n          .using('pet_staging as source', 'source.id', 'target.id')\n          .whenMatched()\n          .thenDelete()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'merge into \"mammals\".\"pet\" as \"target\" using \"mammals\".\"pet_staging\" as \"source\" on \"source\".\"id\" = \"target\".\"id\" when matched then delete',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'merge into \"mammals\".\"pet\" as \"target\" using \"mammals\".\"pet_staging\" as \"source\" on \"source\".\"id\" = \"target\".\"id\" when matched then delete;',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    })\n\n    describe('with', () => {\n      it('should not add schema for common table expression names', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .with('doggo', (db) =>\n            db.selectFrom('pet').where('pet.name', '=', 'Doggo').selectAll(),\n          )\n          .selectFrom('doggo')\n          .selectAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'with \"doggo\" as (select * from \"mammals\".\"pet\" where \"mammals\".\"pet\".\"name\" = $1) select * from \"doggo\"',\n            parameters: ['Doggo'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'with \"doggo\" as (select * from \"mammals\".\"pet\" where \"mammals\".\"pet\".\"name\" = @1) select * from \"doggo\"',\n            parameters: ['Doggo'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n\n      it('should not add schema for common table expression names in subqueries', async () => {\n        const query = ctx.db\n          .withSchema('mammals')\n          .with('doggo', (qb) =>\n            qb.selectFrom('pet').where('name', '=', 'Doggo').select('pet.id'),\n          )\n          .selectFrom('pet')\n          .select((eb) => [\n            'pet.id',\n            eb.selectFrom('doggo').select('id').as('doggo_id'),\n          ])\n          .selectAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'with \"doggo\" as (select \"mammals\".\"pet\".\"id\" from \"mammals\".\"pet\" where \"name\" = $1) select \"mammals\".\"pet\".\"id\", (select \"id\" from \"doggo\") as \"doggo_id\", * from \"mammals\".\"pet\"',\n            parameters: ['Doggo'],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'with \"doggo\" as (select \"mammals\".\"pet\".\"id\" from \"mammals\".\"pet\" where \"name\" = @1) select \"mammals\".\"pet\".\"id\", (select \"id\" from \"doggo\") as \"doggo_id\", * from \"mammals\".\"pet\"',\n            parameters: ['Doggo'],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    })\n\n    describe('create table', () => {\n      afterEach(async () => {\n        await ctx.db.schema\n          .withSchema('mammals')\n          .dropTable('foo')\n          .ifExists()\n          .execute()\n      })\n\n      it('should add schema for references', async () => {\n        const query = ctx.db.schema\n          .withSchema('mammals')\n          .createTable('foo')\n          .addColumn('bar', 'integer', (col) => col.references('pet.id'))\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'create table \"mammals\".\"foo\" (\"bar\" integer references \"mammals\".\"pet\" (\"id\"))',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'create table \"mammals\".\"foo\" (\"bar\" integer references \"mammals\".\"pet\" (\"id\"))',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    })\n\n    describe('create index', () => {\n      afterEach(async () => {\n        await ctx.db.schema\n          .withSchema('mammals')\n          .dropIndex('pet_id_index')\n          .ifExists()\n          .execute()\n      })\n\n      it('should not add schema for created index', async () => {\n        const query = ctx.db.schema\n          .withSchema('mammals')\n          .createIndex('pet_id_index')\n          .column('id')\n          .on('pet')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'create index \"pet_id_index\" on \"mammals\".\"pet\" (\"id\")',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: 'create index \"pet_id_index\" on \"mammals\".\"pet\" (\"id\")',\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    })\n\n    if (dialect === 'postgres') {\n      describe('drop index', () => {\n        beforeEach(async () => {\n          await ctx.db.schema\n            .withSchema('mammals')\n            .createIndex('pet_id_index')\n            .column('id')\n            .on('pet')\n            .execute()\n        })\n\n        it('should add schema for dropped index', async () => {\n          const query = ctx.db.schema\n            .withSchema('mammals')\n            .dropIndex('pet_id_index')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'drop index \"mammals\".\"pet_id_index\"',\n              parameters: [],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          await query.execute()\n        })\n      })\n    }\n\n    describe('create view', () => {\n      afterEach(async () => {\n        await ctx.db.schema\n          .withSchema('mammals')\n          .dropView('dogs')\n          .ifExists()\n          .execute()\n      })\n\n      it('should add schema for created view', async () => {\n        const query = ctx.db.schema\n          .withSchema('mammals')\n          .createView('dogs')\n          .as(ctx.db.selectFrom('pet').where('species', '=', 'dog').selectAll())\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `create view \"mammals\".\"dogs\" as select * from \"mammals\".\"pet\" where \"species\" = 'dog'`,\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: `create view \"mammals\".\"dogs\" as select * from \"mammals\".\"pet\" where \"species\" = 'dog'`,\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    })\n\n    describe('drop view', () => {\n      beforeEach(async () => {\n        await ctx.db.schema\n          .withSchema('mammals')\n          .createView('dogs')\n          .as(ctx.db.selectFrom('pet').where('species', '=', 'dog').selectAll())\n          .execute()\n      })\n\n      it('should add schema for dropped view', async () => {\n        const query = ctx.db.schema.withSchema('mammals').dropView('dogs')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: `drop view \"mammals\".\"dogs\"`,\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: {\n            sql: `drop view \"mammals\".\"dogs\"`,\n            parameters: [],\n          },\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    })\n\n    async function createTables(): Promise<void> {\n      await ctx.db.schema\n        .createSchema('mammals')\n        .$call((qb) => (dialect === 'postgres' ? qb.ifNotExists() : qb))\n        .execute()\n\n      await Promise.all(\n        ['pet', 'pet_staging'].map(async (tableName) => {\n          const table = createTableWithId(\n            ctx.db.schema.withSchema('mammals'),\n            dialect,\n            tableName,\n          )\n\n          await table\n            .addColumn('name', 'varchar(50)', (col) => col.unique())\n            .addColumn('owner_id', 'integer', (col) =>\n              col\n                .references(\n                  dialect === 'postgres' ? 'public.person.id' : 'dbo.person.id',\n                )\n                .onDelete('cascade'),\n            )\n            .addColumn('species', 'varchar(50)')\n            .execute()\n        }),\n      )\n    }\n\n    async function dropTables(): Promise<void> {\n      await Promise.all(\n        ['pet', 'pet_staging'].map((tableName) =>\n          ctx.db.schema\n            .withSchema('mammals')\n            .dropTable(tableName)\n            .ifExists()\n            .execute(),\n        ),\n      )\n\n      await ctx.db.schema.dropSchema('mammals').ifExists().execute()\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/src/with.test.ts",
    "content": "import { sql } from '../../../'\n\nimport {\n  clearDatabase,\n  destroyTest,\n  initTest,\n  TestContext,\n  testSql,\n  expect,\n  NOT_SUPPORTED,\n  insertDefaultDataSet,\n  DIALECTS,\n} from './test-setup.js'\n\nfor (const dialect of DIALECTS) {\n  describe(`${dialect}: with`, () => {\n    let ctx: TestContext\n\n    before(async function () {\n      ctx = await initTest(this, dialect)\n    })\n\n    beforeEach(async () => {\n      await insertDefaultDataSet(ctx)\n    })\n\n    afterEach(async () => {\n      await clearDatabase(ctx)\n    })\n\n    after(async () => {\n      await destroyTest(ctx)\n    })\n\n    it('should create a select query with common table expressions', async () => {\n      const query = ctx.db\n        .with('jennifer_and_sylvester', (db) =>\n          db\n            .selectFrom('person')\n            .where((eb) =>\n              eb.or([\n                eb('first_name', '=', 'Jennifer'),\n                eb('first_name', '=', 'Sylvester'),\n              ]),\n            )\n            .select(['id', 'first_name', 'gender']),\n        )\n        .with('sylvester', (db) =>\n          db\n            .selectFrom('jennifer_and_sylvester')\n            .where('gender', '=', 'male')\n            .selectAll(),\n        )\n        .selectFrom('sylvester')\n        .selectAll()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'with \"jennifer_and_sylvester\" as (select \"id\", \"first_name\", \"gender\" from \"person\" where (\"first_name\" = $1 or \"first_name\" = $2)), \"sylvester\" as (select * from \"jennifer_and_sylvester\" where \"gender\" = $3) select * from \"sylvester\"',\n          parameters: ['Jennifer', 'Sylvester', 'male'],\n        },\n        mysql: {\n          sql: 'with `jennifer_and_sylvester` as (select `id`, `first_name`, `gender` from `person` where (`first_name` = ? or `first_name` = ?)), `sylvester` as (select * from `jennifer_and_sylvester` where `gender` = ?) select * from `sylvester`',\n          parameters: ['Jennifer', 'Sylvester', 'male'],\n        },\n        mssql: {\n          sql: 'with \"jennifer_and_sylvester\" as (select \"id\", \"first_name\", \"gender\" from \"person\" where (\"first_name\" = @1 or \"first_name\" = @2)), \"sylvester\" as (select * from \"jennifer_and_sylvester\" where \"gender\" = @3) select * from \"sylvester\"',\n          parameters: ['Jennifer', 'Sylvester', 'male'],\n        },\n        sqlite: {\n          sql: 'with \"jennifer_and_sylvester\" as (select \"id\", \"first_name\", \"gender\" from \"person\" where (\"first_name\" = ? or \"first_name\" = ?)), \"sylvester\" as (select * from \"jennifer_and_sylvester\" where \"gender\" = ?) select * from \"sylvester\"',\n          parameters: ['Jennifer', 'Sylvester', 'male'],\n        },\n      })\n\n      const result = await query.execute()\n\n      expect(result).to.have.length(1)\n      expect(Object.keys(result[0]).sort()).to.eql([\n        'first_name',\n        'gender',\n        'id',\n      ])\n      expect(result[0]).to.containSubset({\n        first_name: 'Sylvester',\n        gender: 'male',\n      })\n    })\n\n    it('common table expression names can contain columns', async () => {\n      const query = ctx.db\n        .with('arnold(id, first_name)', (db) =>\n          db\n            .selectFrom('person')\n            .where('first_name', '=', 'Arnold')\n            .select(['id', 'first_name']),\n        )\n        .selectFrom('arnold')\n        .selectAll()\n\n      testSql(query, dialect, {\n        postgres: {\n          sql: 'with \"arnold\"(\"id\", \"first_name\") as (select \"id\", \"first_name\" from \"person\" where \"first_name\" = $1) select * from \"arnold\"',\n          parameters: ['Arnold'],\n        },\n        mysql: {\n          sql: 'with `arnold`(`id`, `first_name`) as (select `id`, `first_name` from `person` where `first_name` = ?) select * from `arnold`',\n          parameters: ['Arnold'],\n        },\n        mssql: {\n          sql: 'with \"arnold\"(\"id\", \"first_name\") as (select \"id\", \"first_name\" from \"person\" where \"first_name\" = @1) select * from \"arnold\"',\n          parameters: ['Arnold'],\n        },\n        sqlite: {\n          sql: 'with \"arnold\"(\"id\", \"first_name\") as (select \"id\", \"first_name\" from \"person\" where \"first_name\" = ?) select * from \"arnold\"',\n          parameters: ['Arnold'],\n        },\n      })\n\n      await query.execute()\n    })\n\n    if (dialect === 'postgres') {\n      it('recursive common table expressions can refer to themselves', async () => {\n        await ctx.db.transaction().execute(async (trx) => {\n          // Create a temporary table that gets dropped when the transaction ends.\n          await trx.schema\n            .createTable('node')\n            .temporary()\n            .addColumn('name', 'varchar', (col) => col.notNull().unique())\n            .addColumn('parent', 'varchar', (col) =>\n              col.references('node.name'),\n            )\n            .onCommit('drop')\n            .execute()\n\n          // Extend the database type with the temporary table.\n          const nodeTrx = trx.withTables<{\n            node: {\n              name: string\n              parent: string | null\n            }\n          }>()\n\n          // Insert some items to the temporary table.\n          await nodeTrx\n            .insertInto('node')\n            .values([\n              { name: 'node3', parent: null },\n              { name: 'node2', parent: 'node3' },\n              { name: 'node1', parent: 'node2' },\n            ])\n            .execute()\n\n          // Fetch a node and all its ancestors using a single recursive CTE.\n          const query = nodeTrx\n            .withRecursive('ancestors(name, parent)', (db) =>\n              db\n                .selectFrom('node')\n                .where('name', '=', 'node1')\n                .select(['name', 'parent'])\n                .unionAll(\n                  db\n                    .selectFrom('node')\n                    .innerJoin('ancestors', 'node.name', 'ancestors.parent')\n                    .select(['node.name', 'node.parent']),\n                ),\n            )\n            .selectFrom('ancestors')\n            .select('name')\n\n          testSql(query, dialect, {\n            postgres: {\n              sql: 'with recursive \"ancestors\"(\"name\", \"parent\") as (select \"name\", \"parent\" from \"node\" where \"name\" = $1 union all select \"node\".\"name\", \"node\".\"parent\" from \"node\" inner join \"ancestors\" on \"node\".\"name\" = \"ancestors\".\"parent\") select \"name\" from \"ancestors\"',\n              parameters: ['node1'],\n            },\n            mysql: NOT_SUPPORTED,\n            mssql: NOT_SUPPORTED,\n            sqlite: NOT_SUPPORTED,\n          })\n\n          const result = await query.execute()\n\n          expect(result).to.eql([\n            { name: 'node1' },\n            { name: 'node2' },\n            { name: 'node3' },\n          ])\n        })\n      })\n\n      it('should create a CTE with `as materialized`', async () => {\n        const query = ctx.db\n          .with(\n            (cte) => cte('person_name').materialized(),\n            (qb) => qb.selectFrom('person').select('first_name'),\n          )\n          .selectFrom('person_name')\n          .select('person_name.first_name')\n          .orderBy('first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'with \"person_name\" as materialized (select \"first_name\" from \"person\") select \"person_name\".\"first_name\" from \"person_name\" order by \"first_name\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n        expect(result).to.eql([\n          { first_name: 'Arnold' },\n          { first_name: 'Jennifer' },\n          { first_name: 'Sylvester' },\n        ])\n      })\n\n      it('should create a CTE with `as not materialized`', async () => {\n        const query = ctx.db\n          .with(\n            (cte) => cte('person_name').notMaterialized(),\n            (qb) => qb.selectFrom('person').select('first_name'),\n          )\n          .selectFrom('person_name')\n          .select('person_name.first_name')\n          .orderBy('first_name')\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'with \"person_name\" as not materialized (select \"first_name\" from \"person\") select \"person_name\".\"first_name\" from \"person_name\" order by \"first_name\"',\n            parameters: [],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n        expect(result).to.eql([\n          { first_name: 'Arnold' },\n          { first_name: 'Jennifer' },\n          { first_name: 'Sylvester' },\n        ])\n      })\n    }\n\n    if (dialect === 'postgres' || dialect === 'mssql' || dialect === 'sqlite') {\n      it('should create an insert query with common table expressions', async () => {\n        const query = ctx.db\n          .with('jennifer', (db) =>\n            db\n              .selectFrom('person')\n              .where('first_name', '=', 'Jennifer')\n              .select(['id', 'first_name', 'gender']),\n          )\n          .insertInto('pet')\n          .values({\n            owner_id: (eb) => eb.selectFrom('jennifer').select('id'),\n            name: 'Catto 2',\n            species: 'cat',\n          })\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'with \"jennifer\" as (select \"id\", \"first_name\", \"gender\" from \"person\" where \"first_name\" = $1) insert into \"pet\" (\"owner_id\", \"name\", \"species\") values ((select \"id\" from \"jennifer\"), $2, $3)',\n            parameters: ['Jennifer', 'Catto 2', 'cat'],\n          },\n          mssql: {\n            sql: 'with \"jennifer\" as (select \"id\", \"first_name\", \"gender\" from \"person\" where \"first_name\" = @1) insert into \"pet\" (\"owner_id\", \"name\", \"species\") values ((select \"id\" from \"jennifer\"), @2, @3)',\n            parameters: ['Jennifer', 'Catto 2', 'cat'],\n          },\n          sqlite: {\n            sql: 'with \"jennifer\" as (select \"id\", \"first_name\", \"gender\" from \"person\" where \"first_name\" = ?) insert into \"pet\" (\"owner_id\", \"name\", \"species\") values ((select \"id\" from \"jennifer\"), ?, ?)',\n            parameters: ['Jennifer', 'Catto 2', 'cat'],\n          },\n          mysql: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should create a with query where CTEs are inserts updates and deletes', async () => {\n        const query = ctx.db\n          .with('deleted_arnold', (db) =>\n            db\n              .deleteFrom('person')\n              .where('first_name', '=', 'Arnold')\n              .returning('first_name as deleted_first_name'),\n          )\n          .with('inserted_matt', (db) =>\n            db\n              .insertInto('person')\n              .values({\n                first_name: 'Matt',\n                last_name: 'Damon',\n                gender: 'male',\n              })\n              .returning('first_name as inserted_first_name'),\n          )\n          .with('updated_jennifer', (db) =>\n            db\n              .updateTable('person')\n              .where('first_name', '=', 'Jennifer')\n              .set({ last_name: 'Lawrence' })\n              .returning('first_name as updated_first_name'),\n          )\n          .selectFrom('deleted_arnold')\n          .innerJoin('inserted_matt', (join) => join.on(sql`1`, '=', sql`1`))\n          .innerJoin('updated_jennifer', (join) => join.on(sql`1`, '=', sql`1`))\n          .selectAll()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'with \"deleted_arnold\" as (delete from \"person\" where \"first_name\" = $1 returning \"first_name\" as \"deleted_first_name\"), \"inserted_matt\" as (insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($2, $3, $4) returning \"first_name\" as \"inserted_first_name\"), \"updated_jennifer\" as (update \"person\" set \"last_name\" = $5 where \"first_name\" = $6 returning \"first_name\" as \"updated_first_name\") select * from \"deleted_arnold\" inner join \"inserted_matt\" on 1 = 1 inner join \"updated_jennifer\" on 1 = 1',\n            parameters: [\n              'Arnold',\n              'Matt',\n              'Damon',\n              'male',\n              'Lawrence',\n              'Jennifer',\n            ],\n          },\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n          mysql: NOT_SUPPORTED,\n        })\n\n        const result = await query.execute()\n        expect(result).to.have.length(1)\n        expect(result[0]).to.eql({\n          deleted_first_name: 'Arnold',\n          inserted_first_name: 'Matt',\n          updated_first_name: 'Jennifer',\n        })\n      })\n    }\n\n    if (dialect === 'postgres') {\n      it('should create a merge query with common table expressions that include writes', async () => {\n        const query = ctx.db\n          .with('deleted_arnold', (db) =>\n            db.deleteFrom('person').where('first_name', '=', 'Arnold'),\n          )\n          .with('inserted_matt', (db) =>\n            db.insertInto('person').values({\n              first_name: 'Matt',\n              last_name: 'Damon',\n              gender: 'male',\n            }),\n          )\n          .with('updated_jennifer', (db) =>\n            db\n              .updateTable('person')\n              .where('first_name', '=', 'Jennifer')\n              .set({ last_name: 'Lawrence' })\n              .returning('first_name'),\n          )\n          .mergeInto('person')\n          .using('updated_jennifer', (join) => join.onTrue())\n          .whenMatched()\n          .thenDoNothing()\n\n        testSql(query, dialect, {\n          postgres: {\n            sql: 'with \"deleted_arnold\" as (delete from \"person\" where \"first_name\" = $1), \"inserted_matt\" as (insert into \"person\" (\"first_name\", \"last_name\", \"gender\") values ($2, $3, $4)), \"updated_jennifer\" as (update \"person\" set \"last_name\" = $5 where \"first_name\" = $6 returning \"first_name\") merge into \"person\" using \"updated_jennifer\" on true when matched then do nothing',\n            parameters: [\n              'Arnold',\n              'Matt',\n              'Damon',\n              'male',\n              'Lawrence',\n              'Jennifer',\n            ],\n          },\n          mysql: NOT_SUPPORTED,\n          mssql: NOT_SUPPORTED,\n          sqlite: NOT_SUPPORTED,\n        })\n\n        await query.execute()\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "test/node/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig-base.json\",\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"lib\": [\"ESNext\"],\n    \"module\": \"CommonJS\",\n    \"outDir\": \"dist\",\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"types\": [\"mocha\"],\n    \"rootDir\": \"./src\"\n  }\n}\n"
  },
  {
    "path": "test/outdated-ts/outdated-ts.test.ts",
    "content": "import { Kysely, RawBuilder, sql } from 'kysely'\nimport { KyselyTypeError } from '../../src/util/type-error'\n\nfunction expectOutdatedTSError(\n  _: KyselyTypeError<'The installed TypeScript version is outdated and cannot guarantee type-safety with Kysely. Please upgrade to version 4.6 or newer.'>,\n): void {}\n\nexpectOutdatedTSError(Kysely)\nexpectOutdatedTSError(RawBuilder)\nexpectOutdatedTSError(sql)\n"
  },
  {
    "path": "test/outdated-ts/package.json",
    "content": "{\n  \"name\": \"outdated-ts\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"tsc --noEmit\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"description\": \"\",\n  \"dependencies\": {\n    \"kysely\": \"file:../../\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"4.5.x\"\n  }\n}\n"
  },
  {
    "path": "test/outdated-ts/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig-base.json\",\n  \"include\": [\"./**/*\"],\n  \"compilerOptions\": {\n    \"skipLibCheck\": true\n  }\n}\n"
  },
  {
    "path": "test/scripts/mysql-init.sql",
    "content": "CREATE USER 'kysely'@'%' IDENTIFIED WITH mysql_native_password BY 'kysely';\nGRANT ALL ON *.* TO 'kysely'@'%';\nCREATE DATABASE kysely_test;"
  },
  {
    "path": "test/ts-benchmarks/index.ts",
    "content": "import './select-from.bench.ts'\nimport './order-by.bench.ts'\n"
  },
  {
    "path": "test/ts-benchmarks/order-by.bench.ts",
    "content": "import { bench } from '@ark/attest'\nimport type { DB } from '../typings/test-d/huge-db.test-d'\nimport {\n  type SelectQueryBuilder,\n  sql,\n  type Kysely,\n} from '../../dist/esm/index.js'\n\ndeclare const kysely: Kysely<DB>\ndeclare const kyselyAny: Kysely<any>\n\nlet query: SelectQueryBuilder<\n  DB,\n  'my_table',\n  {\n    e862ca: string | null\n  }\n>\nlet queryAny: SelectQueryBuilder<any, 'my_table', { e862ca: string | null }>\n\nconsole.log('orderBy.bench.ts:\\n')\n\nbench.baseline(() => {\n  query = kysely\n    .selectFrom('my_table')\n    .select('my_table.col_6f7a0a5f582c69dd4c6be0a819e862cb as e862ca')\n\n  queryAny = kyselyAny\n    .selectFrom('my_table')\n    .select('my_table.col_6f7a0a5f582c69dd4c6be0a819e862cb as e862ca')\n})\n\nbench('kysely..orderBy(column)', () =>\n  query.orderBy('col_164b7896ec8e770207febe0812c5f052'),\n).types([69, 'instantiations'])\n\nbench('kysely..orderBy(~column)', () =>\n  // @ts-expect-error\n  query.orderBy('col_164b7896ec8e770207febe0812c5f052_'),\n).types([189, 'instantiations'])\n\nbench('kysely..orderBy(O)', () => query.orderBy('e862ca')).types([\n  69,\n  'instantiations',\n])\n\nbench('kysely..orderBy(column, asc)', () =>\n  query.orderBy('col_164b7896ec8e770207febe0812c5f052', 'asc'),\n).types([69, 'instantiations'])\n\nbench('kysely..orderBy(~column, asc)', () =>\n  // @ts-expect-error\n  query.orderBy('col_164b7896ec8e770207febe0812c5f052_', 'asc'),\n).types([113, 'instantiations'])\n\nbench('kysely..orderBy(column, ~asc)', () =>\n  // @ts-expect-error\n  query.orderBy('col_164b7896ec8e770207febe0812c5f052', 'asc_'),\n).types([103, 'instantiations'])\n\nbench('kysely..orderBy(column, desc)', () =>\n  query.orderBy('col_164b7896ec8e770207febe0812c5f052', 'desc'),\n).types([69, 'instantiations'])\n\nbench('kysely..orderBy(column, ob)', async () =>\n  query.orderBy('col_164b7896ec8e770207febe0812c5f052', (ob) =>\n    ob.asc().nullsLast(),\n  ),\n).types([69, 'instantiations'])\n\nbench('kysely..orderBy(sql)', () =>\n  query.orderBy(sql`col_164b7896ec8e770207febe0812c5f052 asc nulls first`),\n).types([94, 'instantiations'])\n\nbench('kysely..orderBy(select)', () =>\n  query.orderBy(\n    kysely\n      .selectFrom('table_000a8a0cb7f265a624c851d3e7f8b946')\n      .select(\n        'table_000a8a0cb7f265a624c851d3e7f8b946.col_454ff479a3b5a9ef082d9be9ac02a6f4',\n      )\n      .limit(1),\n  ),\n).types([537, 'instantiations'])\n\nbench('kysely..orderBy(eb => select)', () =>\n  query.orderBy((eb) =>\n    eb\n      .selectFrom('table_000a8a0cb7f265a624c851d3e7f8b946')\n      .select(\n        'table_000a8a0cb7f265a624c851d3e7f8b946.col_454ff479a3b5a9ef082d9be9ac02a6f4',\n      )\n      .limit(1),\n  ),\n).types([686, 'instantiations'])\n\nbench('deprecated - kysely..orderBy(column desc)', () =>\n  query.orderBy('col_164b7896ec8e770207febe0812c5f052 desc'),\n).types([170, 'instantiations'])\n\nbench('deprecated - kysely..orderBy([column])', () =>\n  query.orderBy(['col_164b7896ec8e770207febe0812c5f052']),\n).types([152, 'instantiations'])\n\nbench('kysely..orderBy(column).orderBy(column)', () =>\n  query\n    .orderBy('col_164b7896ec8e770207febe0812c5f052')\n    .orderBy('col_1d726898491fbca9a8dac855d2be1be8'),\n).types([75, 'instantiations'])\n\nbench('deprecated - kysely..orderBy([column, column])', () =>\n  query.orderBy([\n    'col_164b7896ec8e770207febe0812c5f052',\n    'col_6f7a0a5f582c69dd4c6be0a819e862cb',\n  ]),\n).types([152, 'instantiations'])\n\nbench('kysely..orderBy(column).orderBy(column, desc)', () =>\n  query\n    .orderBy('col_1d726898491fbca9a8dac855d2be1be8')\n    .orderBy('col_164b7896ec8e770207febe0812c5f052', 'desc'),\n).types([75, 'instantiations'])\n\nbench('deprecated - kysely..orderBy([column, column desc])', () =>\n  query.orderBy([\n    'col_6f7a0a5f582c69dd4c6be0a819e862cb',\n    'col_164b7896ec8e770207febe0812c5f052 desc',\n  ]),\n).types([152, 'instantiations'])\n\nbench('kysely..orderBy(column).orderBy(column).orderBy(column)', () =>\n  query\n    .orderBy('col_164b7896ec8e770207febe0812c5f052')\n    .orderBy('col_1d726898491fbca9a8dac855d2be1be8')\n    .orderBy('col_af4e225b70a9bbd83cc3bc0e7ef24cfa'),\n).types([81, 'instantiations'])\n\nbench('deprecated - kysely..orderBy([column, column, column])', () =>\n  query.orderBy([\n    'col_164b7896ec8e770207febe0812c5f052',\n    'col_6f7a0a5f582c69dd4c6be0a819e862cb',\n    'col_af4e225b70a9bbd83cc3bc0e7ef24cfa',\n  ]),\n).types([152, 'instantiations'])\n\n//\n\nbench('kyselyAny..orderBy(column)', () =>\n  queryAny.orderBy('col_164b7896ec8e770207febe0812c5f052'),\n).types([69, 'instantiations'])\n\nbench('kyselyAny..orderBy(~column)', () =>\n  queryAny.orderBy('col_164b7896ec8e770207febe0812c5f052_'),\n).types([69, 'instantiations'])\n\nbench('kyselyAny..orderBy(O)', () => queryAny.orderBy('e862ca')).types([\n  69,\n  'instantiations',\n])\n\nbench('kyselyAny..orderBy(column, asc)', () =>\n  queryAny.orderBy('col_164b7896ec8e770207febe0812c5f052', 'asc'),\n).types([69, 'instantiations'])\n\nbench('kyselyAny..orderBy(~column, asc)', () =>\n  queryAny.orderBy('col_164b7896ec8e770207febe0812c5f052_', 'asc'),\n).types([69, 'instantiations'])\n\nbench('kyselyAny..orderBy(column, ~asc)', () =>\n  // @ts-expect-error\n  queryAny.orderBy('col_164b7896ec8e770207febe0812c5f052', 'asc_'),\n).types([103, 'instantiations'])\n\nbench('kyselyAny..orderBy(column, desc)', () =>\n  queryAny.orderBy('col_164b7896ec8e770207febe0812c5f052', 'desc'),\n).types([69, 'instantiations'])\n\nbench('kyselyAny..orderBy(column, ob)', async () =>\n  queryAny.orderBy('col_164b7896ec8e770207febe0812c5f052', (ob) =>\n    ob.asc().nullsLast(),\n  ),\n).types([69, 'instantiations'])\n\nbench('kyselyAny..orderBy(sql)', () =>\n  queryAny.orderBy(sql`col_164b7896ec8e770207febe0812c5f052 asc nulls first`),\n).types([94, 'instantiations'])\n\nbench('kyselyAny..orderBy(select)', () =>\n  queryAny.orderBy(\n    kyselyAny\n      .selectFrom('table_000a8a0cb7f265a624c851d3e7f8b946')\n      .select(\n        'table_000a8a0cb7f265a624c851d3e7f8b946.col_454ff479a3b5a9ef082d9be9ac02a6f4',\n      )\n      .limit(1),\n  ),\n).types([279, 'instantiations'])\n\nbench('kyselyAny..orderBy(eb => select)', () =>\n  queryAny.orderBy((eb) =>\n    eb\n      .selectFrom('table_000a8a0cb7f265a624c851d3e7f8b946')\n      .select('col_164b7896ec8e770207febe0812c5f052')\n      .limit(1),\n  ),\n).types([368, 'instantiations'])\n"
  },
  {
    "path": "test/ts-benchmarks/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "test/ts-benchmarks/select-from.bench.ts",
    "content": "import { bench } from '@ark/attest'\nimport type { DB } from '../typings/test-d/huge-db.test-d'\nimport type { Kysely } from '../../dist/esm/index.js'\n\ndeclare const kysely: Kysely<DB>\ndeclare const kyselyAny: Kysely<any>\n\nconsole.log('selectFrom.bench.ts:\\n')\n\nbench.baseline(() => {})\n\nbench('kysely.selectFrom(table)', () => {\n  return kysely.selectFrom('table_fff4c6195261874920bc7ce92d67d2c2')\n}).types([343, 'instantiations'])\n\nbench('kysely.selectFrom(~table)', () => {\n  // @ts-expect-error\n  return kysely.selectFrom('my_table2')\n}).types([5086, 'instantiations'])\n\nbench('kysely.selectFrom(table as alias)', () => {\n  return kysely.selectFrom('my_table as mt')\n}).types([357, 'instantiations'])\n\nbench('kysely.selectFrom([table])', () => {\n  return kysely.selectFrom(['my_table'])\n}).types([380, 'instantiations'])\n\nbench('kysely.selectFrom([~table])', () => {\n  // @ts-expect-error\n  return kysely.selectFrom(['my_table2'])\n}).types([5127, 'instantiations'])\n\nbench('kysely.selectFrom([table as alias])', () => {\n  return kysely.selectFrom(['my_table as mt'])\n}).types([380, 'instantiations'])\n\nbench('kysely.selectFrom([table, table])', () => {\n  return kysely.selectFrom([\n    'my_table',\n    'table_000a8a0cb7f265a624c851d3e7f8b946',\n  ])\n}).types([380, 'instantiations'])\n\nbench('kysely.selectFrom([table, ~table])', () => {\n  return kysely.selectFrom([\n    'my_table',\n    // @ts-expect-error\n    'table_000a8a0cb7f265a624c851d3e7f8b9462',\n  ])\n}).types([5130, 'instantiations'])\n\nbench('kysely.selectFrom([table as alias, table as alias])', () => {\n  return kysely.selectFrom([\n    'my_table as mt',\n    'table_000a8a0cb7f265a624c851d3e7f8b946 as t',\n  ])\n}).types([380, 'instantiations'])\n\nbench('kysely.selectFrom(kysely.selectFrom(table).as(t))', () => {\n  return kysely.selectFrom(kysely.selectFrom('my_table').as('t'))\n}).types([1230, 'instantiations'])\n\nbench('kyselyAny.selectFrom(table)', () => {\n  return kyselyAny.selectFrom('table_fff4c6195261874920bc7ce92d67d2c2')\n}).types([95, 'instantiations'])\n\nbench('kyselyAny.selectFrom(~table)', () => {\n  return kyselyAny.selectFrom('my_table2')\n}).types([95, 'instantiations'])\n\nbench('kyselyAny.selectFrom(table as alias)', () => {\n  return kyselyAny.selectFrom('my_table as mt')\n}).types([95, 'instantiations'])\n\nbench('kyselyAny.selectFrom([table])', () => {\n  return kyselyAny.selectFrom(['my_table'])\n}).types([132, 'instantiations'])\n\nbench('kyselyAny.selectFrom([~table])', () => {\n  return kyselyAny.selectFrom(['my_table2'])\n}).types([132, 'instantiations'])\n\nbench('kyselyAny.selectFrom([table as alias])', () => {\n  return kyselyAny.selectFrom(['my_table as mt'])\n}).types([132, 'instantiations'])\n\nbench('kyselyAny.selectFrom([table, table])', () => {\n  return kyselyAny.selectFrom([\n    'my_table',\n    'table_000a8a0cb7f265a624c851d3e7f8b946',\n  ])\n}).types([132, 'instantiations'])\n\nbench('kyselyAny.selectFrom([table, ~table])', () => {\n  return kyselyAny.selectFrom([\n    'my_table',\n    'table_000a8a0cb7f265a624c851d3e7f8b9462',\n  ])\n}).types([132, 'instantiations'])\n\nbench('kyselyAny.selectFrom([table as alias, table as alias])', () => {\n  return kyselyAny.selectFrom([\n    'my_table as mt',\n    'table_000a8a0cb7f265a624c851d3e7f8b946 as t',\n  ])\n}).types([132, 'instantiations'])\n"
  },
  {
    "path": "test/ts-benchmarks/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig-base.json\",\n  \"include\": [\"**/*.ts\"]\n}\n"
  },
  {
    "path": "test/typings/index.d.ts",
    "content": "export * from '../../'\nexport * from '../../helpers/postgres'\n"
  },
  {
    "path": "test/typings/package.json",
    "content": "{\n  \"types\": \"index.d.ts\",\n  \"tsd\": {\n    \"compilerOptions\": {\n      \"exactOptionalPropertyTypes\": true\n    }\n  }\n}\n"
  },
  {
    "path": "test/typings/shared.d.ts",
    "content": "import {\n  ColumnType,\n  Generated,\n  GeneratedAlways,\n  JSONColumnType,\n} from '../../dist/cjs'\n\nexport interface Pet {\n  id: Generated<string>\n  name: string\n  owner_id: number\n  species: 'dog' | 'cat'\n}\n\nexport interface Toy {\n  id: Generated<string>\n  price: number\n  pet_id: string\n}\n\nexport interface Movie {\n  id: Generated<string>\n  stars: number\n}\n\nexport interface Book {\n  id: GeneratedAlways<number>\n  name: string\n}\n\nexport interface Database {\n  person: Person\n  pet: Pet\n  movie: Movie\n  'some_schema.movie': Movie\n  book: Book\n  toy: Toy\n  person_metadata: PersonMetadata\n  action: Action\n}\n\nexport type Action =\n  | {\n      id: GeneratedAlways<string>\n      type: 'CALL_WEBHOOK'\n      queue_id: null\n      callback_url: string\n    }\n  | {\n      id: GeneratedAlways<string>\n      type: 'DELETE_FROM_QUEUE'\n      queue_id: string\n      callback_url: null\n    }\n\nexport interface Person {\n  id: Generated<number>\n  first_name: string\n  last_name: string | null\n  age: number\n  gender: 'male' | 'female' | 'other'\n  marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n  // A Column that is generated by the DB and which\n  // we never want the user to be able to insert or\n  // update.\n  modified_at: ColumnType<Date, never, never>\n  // A column that cannot be inserted, but can be updated.\n  deleted_at: ColumnType<Date | null, never, string | undefined>\n}\n\nexport interface PersonMetadata {\n  id: Generated<number>\n  person_id: number\n  website: JSONColumnType<{ url: string }>\n  nicknames: JSONColumnType<string[]>\n  profile: JSONColumnType<{\n    auth: {\n      roles: string[]\n      last_login?: { device: string }\n    }\n    tags: string[]\n  }>\n  experience: JSONColumnType<\n    {\n      establishment: string\n    }[]\n  >\n  schedule: JSONColumnType<{ name: string; time: string }[][][]>\n  record: JSONColumnType<Record<string, string>>\n  array: JSONColumnType<Array<string>>\n}\n"
  },
  {
    "path": "test/typings/test-d/aggregate-function.test-d.ts",
    "content": "import {\n  expectError,\n  expectAssignable,\n  expectNotAssignable,\n  expectType,\n} from 'tsd'\nimport { type Generated, type Kysely, sql } from '..'\nimport type { Database } from '../shared'\n\nasync function testSelectWithoutAs(db: Kysely<Database>) {\n  const { avg, count, countAll, max, min, sum } = db.fn\n\n  expectError(\n    db.selectFrom('person').select(avg('age')).executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(avg<number>('age'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db.selectFrom('person').select(count('age')).executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(count<number>('age'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db.selectFrom('person').select(countAll()).executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(countAll<number>())\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(countAll('person'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(countAll<number>('person'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db.selectFrom('person').select(max('age')).executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db.selectFrom('person').select(min('age')).executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db.selectFrom('person').select(sum('age')).executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(sum<number>('age'))\n      .executeTakeFirstOrThrow(),\n  )\n}\n\nasync function testSelectWithDefaultGenerics(db: Kysely<Database>) {\n  const { avg, count, countAll, max, min, sum } = db.fn\n\n  const result = await db\n    .selectFrom('person')\n    .select(avg('age').as('avg_age'))\n    .select(count('age').as('total_people'))\n    .select(countAll().as('total_all'))\n    .select(countAll('person').as('total_all_people'))\n    .select(max('age').as('max_age'))\n    .select(min('age').as('min_age'))\n    .select(sum('age').as('total_age'))\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<string | number>(result.avg_age)\n  expectNotAssignable<null>(result.avg_age)\n  expectAssignable<string | number | bigint>(result.total_people)\n  expectNotAssignable<null>(result.total_people)\n  expectAssignable<string | number | bigint>(result.total_all)\n  expectNotAssignable<null>(result.total_all)\n  expectAssignable<string | number | bigint>(result.total_all_people)\n  expectNotAssignable<null>(result.total_all_people)\n  expectAssignable<number>(result.max_age)\n  expectNotAssignable<string | bigint | null>(result.max_age)\n  expectAssignable<number>(result.min_age)\n  expectNotAssignable<string | bigint | null>(result.min_age)\n  expectAssignable<string | number | bigint>(result.total_age)\n  expectNotAssignable<null>(result.total_age)\n}\n\nasync function testSelectExpressionBuilderWithDefaultGenerics(\n  db: Kysely<Database>,\n) {\n  const result = await db\n    .selectFrom('person')\n    .select((eb) => [\n      eb.fn.avg('age').as('avg_age'),\n      eb.fn.count('age').as('total_people'),\n      eb.fn.countAll().as('total_all'),\n      eb.fn.countAll('person').as('total_all_people'),\n      eb.fn.max('age').as('max_age'),\n      eb.fn.min('age').as('min_age'),\n      eb.fn.sum('age').as('total_age'),\n    ])\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<string | number>(result.avg_age)\n  expectNotAssignable<null>(result.avg_age)\n  expectAssignable<string | number | bigint>(result.total_people)\n  expectNotAssignable<null>(result.total_people)\n  expectAssignable<string | number | bigint>(result.total_all)\n  expectNotAssignable<null>(result.total_all)\n  expectAssignable<string | number | bigint>(result.total_all_people)\n  expectNotAssignable<null>(result.total_all_people)\n  expectAssignable<number>(result.max_age)\n  expectNotAssignable<string | bigint | null>(result.max_age)\n  expectAssignable<number>(result.min_age)\n  expectNotAssignable<string | bigint | null>(result.min_age)\n  expectAssignable<string | number | bigint>(result.total_age)\n  expectNotAssignable<null>(result.total_age)\n}\n\nasync function testSelectExpressionBuilderWithCustomGenerics(\n  db: Kysely<Database>,\n) {\n  const result = await db\n    .selectFrom('person')\n    .select((eb) => [\n      eb.fn.avg<number>('age').as('avg_age'),\n      eb.fn.count<number>('age').as('total_people'),\n      eb.fn.countAll<number>().as('total_all'),\n      eb.fn.countAll<number>('person').as('total_all_people'),\n      eb.fn.max<number>('age').as('max_age'),\n      eb.fn.min<number>('age').as('min_age'),\n      eb.fn.sum<number>('age').as('total_age'),\n      eb.fn.agg<number>('max', ['age']).as('another_max_age'),\n    ])\n    .executeTakeFirstOrThrow()\n\n  expectType<number>(result.avg_age)\n  expectType<number>(result.total_people)\n  expectType<number>(result.total_all)\n  expectType<number>(result.total_all_people)\n  expectType<number>(result.max_age)\n  expectType<number>(result.min_age)\n  expectType<number>(result.total_age)\n  expectType<number>(result.another_max_age)\n}\n\nasync function testSelectExpressionBuilderWithSubExpressions(\n  db: Kysely<Database>,\n) {\n  const result = await db\n    .selectFrom('person')\n    .select((eb) => [\n      eb.fn.avg(eb.ref('age')).as('avg_age'),\n      eb.fn.count(eb.ref('age')).as('total_people'),\n      eb.fn.countAll().as('total_all'),\n      eb.fn.countAll('person').as('total_all_people'),\n      eb.fn.max(eb.ref('age').$castTo<bigint>()).as('max_age'),\n      eb.fn.min(eb.ref('age')).as('min_age'),\n      eb.fn.sum(eb.ref('age')).as('total_age'),\n    ])\n\n    .executeTakeFirstOrThrow()\n\n  expectType<string | number>(result.avg_age)\n  expectType<string | number | bigint>(result.total_people)\n  expectType<string | number | bigint>(result.total_all)\n  expectType<string | number | bigint>(result.total_all_people)\n  expectType<bigint>(result.max_age)\n  expectType<number>(result.min_age)\n  expectType<string | number | bigint>(result.total_age)\n}\n\nasync function testSelectWithCustomGenerics(db: Kysely<Database>) {\n  const { avg, count, countAll, max, min, sum, agg } = db.fn\n\n  const result = await db\n    .selectFrom('person')\n    .select(avg<number>('age').as('avg_age'))\n    .select(avg<number | null>('age').as('nullable_avg_age'))\n    .select(count<number>('age').as('total_people'))\n    .select(countAll<number>().as('total_all'))\n    .select(countAll<number>('person').as('total_all_people'))\n    .select(max<number | null>('age').as('nullable_max_age'))\n    .select(min<number | null>('age').as('nullable_min_age'))\n    .select(sum<number>('age').as('total_age'))\n    .select(sum<number | null>('age').as('nullable_total_age'))\n    .select(agg<number>('max', ['age']).as('max_age'))\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<number>(result.avg_age)\n  expectNotAssignable<string | bigint | null>(result.avg_age)\n  expectAssignable<number | null>(result.nullable_avg_age)\n  expectNotAssignable<string | bigint>(result.nullable_avg_age)\n  expectAssignable<number>(result.total_people)\n  expectNotAssignable<string | bigint | null>(result.total_people)\n  expectAssignable<number>(result.total_all)\n  expectNotAssignable<string | bigint | null>(result.total_all)\n  expectAssignable<number>(result.total_all_people)\n  expectNotAssignable<string | bigint | null>(result.total_all_people)\n  expectAssignable<number | null>(result.nullable_max_age)\n  expectNotAssignable<string | bigint>(result.nullable_max_age)\n  expectAssignable<number | null>(result.nullable_min_age)\n  expectNotAssignable<string | bigint>(result.nullable_min_age)\n  expectAssignable<number>(result.total_age)\n  expectNotAssignable<string | bigint | null>(result.total_age)\n  expectAssignable<number | null>(result.nullable_total_age)\n  expectNotAssignable<string | bigint>(result.nullable_total_age)\n  expectType<number>(result.max_age)\n}\n\nasync function testSelectUnexpectedColumn(db: Kysely<Database>) {\n  const { avg, count, countAll, max, min, sum } = db.fn\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(avg('no_such_column').as('avg_age'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(avg<number>('no_such_column').as('avg_age'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(count('no_such_column').as('total_people'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(count<number>('no_such_column').as('total_people'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(countAll('no_such_table').as('total_all_people'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(countAll<number>('no_such_table').as('total_all_people'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(max('no_such_column').as('max_age'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(min('no_such_column').as('min_age'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(sum('no_such_column').as('total_age'))\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(sum<number>('no_such_column').as('total_age'))\n      .executeTakeFirstOrThrow(),\n  )\n}\n\nasync function testSelectWithDynamicReference(db: Kysely<Database>) {\n  const { avg, count, max, min, sum } = db.fn\n\n  const dynamicColumn = Math.random().toString()\n\n  const dynamicReference = db.dynamic.ref(dynamicColumn)\n\n  const result = await db\n    .selectFrom('person')\n    .select(avg(dynamicReference).as('avg'))\n    .select(avg<number>(dynamicReference).as('another_avg'))\n    .select(avg<number | null>(dynamicReference).as('nullable_avg'))\n    .select(count(dynamicReference).as('count'))\n    .select(count<bigint>(dynamicReference).as('another_count'))\n    .select(max(dynamicReference).as('max'))\n    .select(max<number>(dynamicReference).as('another_max'))\n    .select(max<number | null>(dynamicReference).as('nullable_max'))\n    .select(min(dynamicReference).as('min'))\n    .select(min<string>(dynamicReference).as('another_min'))\n    .select(max<string | null>(dynamicReference).as('nullable_min'))\n    .select(sum(dynamicReference).as('sum'))\n    .select(sum<number>(dynamicReference).as('another_sum'))\n    .select(sum<number | null>(dynamicReference).as('nullable_sum'))\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<string | number>(result.avg)\n  expectNotAssignable<bigint | null>(result.avg)\n  expectAssignable<number>(result.another_avg)\n  expectNotAssignable<string | bigint | null>(result.another_avg)\n  expectAssignable<number | null>(result.nullable_avg)\n  expectNotAssignable<string | bigint>(result.nullable_avg)\n  expectAssignable<string | number | bigint>(result.count)\n  expectNotAssignable<null>(result.count)\n  expectAssignable<bigint>(result.another_count)\n  expectNotAssignable<string | number | null>(result.another_count)\n  expectAssignable<number | string | Date | bigint>(result.max)\n  expectNotAssignable<null>(result.max)\n  expectAssignable<number>(result.another_max)\n  expectNotAssignable<string | bigint>(result.another_max)\n  expectAssignable<number | null>(result.nullable_max)\n  expectNotAssignable<string | bigint>(result.nullable_max)\n  expectAssignable<number | string | Date | bigint>(result.min)\n  expectNotAssignable<null>(result.min)\n  expectAssignable<string>(result.another_min)\n  expectNotAssignable<number | bigint | null>(result.another_min)\n  expectAssignable<string | null>(result.nullable_min)\n  expectNotAssignable<number | bigint>(result.nullable_min)\n  expectAssignable<string | number | bigint>(result.sum)\n  expectNotAssignable<null>(result.sum)\n  expectAssignable<number>(result.another_sum)\n  expectNotAssignable<string | bigint | null>(result.another_sum)\n  expectAssignable<number | null>(result.nullable_sum)\n  expectNotAssignable<string | bigint>(result.nullable_sum)\n}\n\nasync function testSelectWithDistinct(db: Kysely<Database>) {\n  const { avg, count, max, min, sum } = db.fn\n\n  const result = await db\n    .selectFrom('person')\n    .select(avg('age').distinct().as('avg_age'))\n    .select(count('age').distinct().as('total_people'))\n    .select(max('age').distinct().as('max_age'))\n    .select(min('age').distinct().as('min_age'))\n    .select(sum('age').distinct().as('total_age'))\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<string | number>(result.avg_age)\n  expectAssignable<string | number | bigint>(result.total_people)\n  expectAssignable<number>(result.max_age)\n  expectAssignable<number>(result.min_age)\n  expectAssignable<string | number | bigint>(result.total_age)\n}\n\nasync function testWithFilterWhere(db: Kysely<Database>) {\n  const { avg, count, max, min, sum } = db.fn\n\n  // Column name\n  db.selectFrom('person')\n    .select(avg('age').filterWhere('gender', '=', 'female').as('avg_age'))\n    .select(count('id').filterWhere('gender', '=', 'female').as('female_count'))\n    .select(max('age').filterWhere('gender', '=', 'female').as('max_age'))\n    .select(min('age').filterWhere('gender', '=', 'female').as('min_age'))\n    .select(sum('age').filterWhere('gender', '=', 'female').as('total_age'))\n\n  // Table and column\n  db.selectFrom('person').select(\n    avg('age').filterWhere('person.gender', '=', 'female').as('avg_age'),\n  )\n\n  // Schema, table and column\n  db.selectFrom('some_schema.movie').select(\n    avg('stars').filterWhere('some_schema.movie.stars', '>', 0).as('avg_stars'),\n  )\n\n  // Subquery in LHS\n  db.selectFrom('person').select(\n    avg('age')\n      .filterWhere((qb) => qb.selectFrom('movie').select('stars'), '>', 0)\n      .as('avg_age'),\n  )\n\n  // Subquery in RHS\n  db.selectFrom('movie').select(\n    avg('stars')\n      .filterWhere(sql<string>`${'female'}`, '=', (qb) =>\n        qb.selectFrom('person').select('gender'),\n      )\n      .as('avg_stars'),\n  )\n\n  // Raw expression\n  db.selectFrom('person').select(\n    avg('age')\n      .filterWhere('first_name', '=', sql<string>`'foo'`)\n      .filterWhere('first_name', '=', sql<string>`'foo'`)\n      .filterWhere(sql`whatever`, '=', 1)\n      .filterWhere(sql`whatever`, '=', true)\n      .filterWhere(sql`whatever`, '=', '1')\n      .as('avg_age'),\n  )\n\n  // List value\n  db.selectFrom('person').select(\n    avg('age').filterWhere('gender', 'in', ['female', 'male']).as('avg_age'),\n  )\n\n  // Raw operator\n  db.selectFrom('person').select(\n    avg('age')\n      .filterWhere('person.age', sql`lol`, 25)\n      .as('avg_age'),\n  )\n\n  // Invalid operator\n  expectError(\n    db\n      .selectFrom('person')\n      .select(avg('age').filterWhere('person.age', 'lol', 25).as('avg_age')),\n  )\n\n  // Invalid table\n  expectError(\n    db\n      .selectFrom('person')\n      .select((eb) =>\n        eb.fn.avg('age').filterWhere('movie.stars', '=', 25).as('avg_age'),\n      ),\n  )\n\n  // Invalid column\n  expectError(\n    db\n      .selectFrom('person')\n      .select((eb) =>\n        eb.fn.avg('age').filterWhere('stars', '=', 25).as('avg_age'),\n      ),\n  )\n\n  // Invalid type for column\n  expectError(\n    db\n      .selectFrom('person')\n      .select(avg('age').filterWhere('first_name', '=', 25).as('avg_age')),\n  )\n\n  // Invalid type for column\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        avg('age').filterWhere('gender', '=', 'not_a_gender').as('avg_age'),\n      ),\n  )\n\n  // Invalid type for column\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        avg('age')\n          .filterWhere('gender', 'in', ['female', 'not_a_gender'])\n          .as('avg_age'),\n      ),\n  )\n\n  // Invalid type for column\n  expectError(\n    db\n      .selectFrom('some_schema.movie')\n      .select(\n        avg('stars')\n          .filterWhere('some_schema.movie.id', '=', 1)\n          .as('avg_stars'),\n      ),\n  )\n\n  // Invalid type for column\n  expectError(\n    db.selectFrom('some_schema.movie').select(\n      avg('stars')\n        .filterWhere(\n          (qb) => qb.selectFrom('person').select('gender'),\n          '=',\n          'not_a_gender',\n        )\n        .as('avg_stars'),\n    ),\n  )\n\n  // Invalid type for column\n  expectError(\n    db.selectFrom('person').select(\n      avg('age')\n        .filterWhere('first_name', '=', sql<number>`1`)\n        .as('avg_age'),\n    ),\n  )\n\n  // Invalid type for column\n  expectError(\n    db.selectFrom('person').select(\n      avg('age')\n        .filterWhere(sql<string>`first_name`, '=', 1)\n        .as('avg_age'),\n    ),\n  )\n}\n\nasync function testWithFilterWhereRef(db: Kysely<Database>) {\n  const { avg, count, max, min, sum } = db.fn\n\n  // Column name\n  db.selectFrom('person')\n    .select(\n      avg('age').filterWhereRef('first_name', '=', 'last_name').as('avg_age'),\n    )\n    .select(\n      count('id').filterWhereRef('first_name', '=', 'last_name').as('count'),\n    )\n    .select(\n      max('age').filterWhereRef('first_name', '=', 'last_name').as('max_age'),\n    )\n    .select(\n      min('age').filterWhereRef('first_name', '=', 'last_name').as('min_age'),\n    )\n    .select(\n      sum('age').filterWhereRef('first_name', '=', 'last_name').as('total_age'),\n    )\n\n  // Table and column\n  db.selectFrom('person')\n    .select(\n      avg('age')\n        .filterWhereRef('person.first_name', '=', 'last_name')\n        .as('avg_age'),\n    )\n    .select(\n      count('id')\n        .filterWhereRef('first_name', '=', 'person.last_name')\n        .as('count'),\n    )\n    .select(\n      max('age')\n        .filterWhereRef('person.first_name', '=', 'person.last_name')\n        .as('max_age'),\n    )\n\n  // Schema, table and column\n  db.selectFrom('movie')\n    .select(\n      avg('stars')\n        .filterWhereRef('some_schema.movie.id', '=', 'stars')\n        .as('avg_stars'),\n    )\n    .select(\n      count('id')\n        .filterWhereRef('some_schema.movie.id', '=', 'movie.stars')\n        .as('count'),\n    )\n    .select(\n      max('stars')\n        .filterWhereRef('some_schema.movie.id', '=', 'some_schema.movie.stars')\n        .as('max_stars'),\n    )\n    .select(\n      min('stars')\n        .filterWhereRef('movie.id', '=', 'some_schema.movie.stars')\n        .as('min_stars'),\n    )\n    .select(\n      sum('stars')\n        .filterWhereRef('id', '=', 'some_schema.movie.stars')\n        .as('total_stars'),\n    )\n\n  // Subquery in LHS\n  db.selectFrom('person').select(\n    avg('age')\n      .filterWhereRef(\n        (qb) => qb.selectFrom('movie').select('stars'),\n        '>',\n        'age',\n      )\n      .as('avg_age'),\n  )\n\n  // Subquery in RHS\n  db.selectFrom('person').select(\n    avg('age')\n      .filterWhereRef('age', '>', (qb) =>\n        qb.selectFrom('movie').select('stars'),\n      )\n      .as('avg_age'),\n  )\n\n  // Raw operator\n  db.selectFrom('person').select(\n    avg('age')\n      .filterWhereRef('first_name', sql`lol`, 'last_name')\n      .as('avg_age'),\n  )\n\n  // Invalid operator\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        avg('age')\n          .filterWhereRef('first_name', 'lol', 'last_name')\n          .as('avg_age'),\n      ),\n  )\n\n  // Invalid table LHS\n  expectError(\n    db\n      .selectFrom('person')\n      .select((eb) =>\n        eb.fn\n          .avg('age')\n          .filterWhereRef('movie.stars', '>', 'age')\n          .as('avg_age'),\n      ),\n  )\n\n  // Invalid table RHS\n  expectError(\n    db\n      .selectFrom('person')\n      .select((eb) =>\n        eb.fn\n          .avg('age')\n          .filterWhereRef('age', '>', 'movie.stars')\n          .as('avg_age'),\n      ),\n  )\n\n  // Invalid column LHS\n  expectError(\n    db\n      .selectFrom('person')\n      .select((eb) =>\n        eb.fn.avg('age').filterWhereRef('stars', '>', 'age').as('avg_age'),\n      ),\n  )\n\n  // Invalid column RHS\n  expectError(\n    db\n      .selectFrom('person')\n      .select((eb) =>\n        eb.fn.avg('age').filterWhereRef('age', '>', 'stars').as('avg_age'),\n      ),\n  )\n}\n\nasync function testSelectWithOver(db: Kysely<Database>) {\n  const { avg, count, max, min, sum } = db.fn\n\n  const result = await db\n    .selectFrom('person')\n    .select(avg('age').over().as('avg_age'))\n    .select(count('age').over().as('total_people'))\n    .select(max('age').over().as('max_age'))\n    .select(min('age').over().as('min_age'))\n    .select(sum('age').over().as('total_age'))\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<string | number>(result.avg_age)\n  expectAssignable<string | number | bigint>(result.total_people)\n  expectAssignable<number>(result.max_age)\n  expectAssignable<number>(result.min_age)\n  expectAssignable<string | number | bigint>(result.total_age)\n}\n\nasync function testSelectWithOverAndPartitionBySingle(db: Kysely<Database>) {\n  const { avg, count, max, min, sum } = db.fn\n\n  const result = await db\n    .selectFrom('person')\n    .select(\n      avg('age')\n        .over((ob) => ob.partitionBy('gender'))\n        .as('avg_age'),\n    )\n    .select(\n      count('age')\n        .over((ob) => ob.partitionBy('gender'))\n        .as('total_people'),\n    )\n    .select(\n      max('age')\n        .over((ob) => ob.partitionBy('gender'))\n        .as('max_age'),\n    )\n    .select(\n      min('age')\n        .over((ob) => ob.partitionBy('gender'))\n        .as('min_age'),\n    )\n    .select(\n      sum('age')\n        .over((ob) => ob.partitionBy('gender'))\n        .as('total_age'),\n    )\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<string | number>(result.avg_age)\n  expectAssignable<string | number | bigint>(result.total_people)\n  expectAssignable<number>(result.max_age)\n  expectAssignable<number>(result.min_age)\n  expectAssignable<string | number | bigint>(result.total_age)\n}\n\nasync function testSelectWithOverAndPartitionByMultiple(db: Kysely<Database>) {\n  const { avg, count, max, min, sum } = db.fn\n\n  const result = await db\n    .selectFrom('person')\n    .select(\n      avg('age')\n        .over((ob) => ob.partitionBy(['gender']))\n        .as('avg_age'),\n    )\n    .select(\n      count('age')\n        .over((ob) =>\n          ob.partitionBy(['gender']).partitionBy('person.first_name'),\n        )\n        .as('total_people'),\n    )\n    .select(\n      max('age')\n        .over((ob) =>\n          ob.partitionBy(['gender']).partitionBy('person.first_name'),\n        )\n        .as('max_age'),\n    )\n    .select(\n      min('age')\n        .over((ob) =>\n          ob.partitionBy(['gender']).partitionBy('person.first_name'),\n        )\n        .as('min_age'),\n    )\n    .select(\n      sum('age')\n        .over((ob) =>\n          ob.partitionBy(['gender']).partitionBy('person.first_name'),\n        )\n        .as('total_age'),\n    )\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<string | number>(result.avg_age)\n  expectAssignable<string | number | bigint>(result.total_people)\n  expectAssignable<number>(result.max_age)\n  expectAssignable<number>(result.min_age)\n  expectAssignable<string | number | bigint>(result.total_age)\n}\n\nasync function testSelectWithOverAndPartitionByUnexpectedColumns(\n  db: Kysely<Database>,\n) {\n  const { avg, count, max, min, sum } = db.fn\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        avg('age')\n          .over((ob) => ob.partitionBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        avg('age')\n          .over((ob) => ob.partitionBy(['no_such_column']))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        count('age')\n          .over((ob) => ob.partitionBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        count('age')\n          .over((ob) => ob.partitionBy(['no_such_column']))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        max('age')\n          .over((ob) => ob.partitionBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        max('age')\n          .over((ob) => ob.partitionBy(['no_such_column']))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        min('age')\n          .over((ob) => ob.partitionBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        min('age')\n          .over((ob) => ob.partitionBy(['no_such_column']))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        sum('age')\n          .over((ob) => ob.partitionBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        sum('age')\n          .over((ob) => ob.partitionBy(['no_such_column']))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n}\n\nasync function testSelectWithOverAndOrderBySingle(db: Kysely<Database>) {\n  const { avg, count, max, min, sum } = db.fn\n\n  const result = await db\n    .selectFrom('person')\n    .select(\n      avg('age')\n        .over((ob) => ob.orderBy('gender'))\n        .as('avg_age'),\n    )\n    .select(\n      count('age')\n        .over((ob) => ob.orderBy('gender'))\n        .as('total_people'),\n    )\n    .select(\n      max('age')\n        .over((ob) => ob.orderBy('gender'))\n        .as('max_age'),\n    )\n    .select(\n      min('age')\n        .over((ob) => ob.orderBy('gender'))\n        .as('min_age'),\n    )\n    .select(\n      sum('age')\n        .over((ob) => ob.orderBy('gender'))\n        .as('total_age'),\n    )\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<string | number>(result.avg_age)\n  expectAssignable<string | number | bigint>(result.total_people)\n  expectAssignable<number>(result.max_age)\n  expectAssignable<number>(result.min_age)\n  expectAssignable<string | number | bigint>(result.total_age)\n}\n\nasync function testSelectWithOverAndOrderByMultiple(db: Kysely<Database>) {\n  const { avg, count, max, min, sum } = db.fn\n\n  const result = await db\n    .selectFrom('person')\n    .select(\n      avg('age')\n        .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc'))\n        .as('avg_age'),\n    )\n    .select(\n      count('age')\n        .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc'))\n        .as('total_people'),\n    )\n    .select(\n      max('age')\n        .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc'))\n        .as('max_age'),\n    )\n    .select(\n      min('age')\n        .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc'))\n        .as('min_age'),\n    )\n    .select(\n      sum('age')\n        .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc'))\n        .as('total_age'),\n    )\n    .executeTakeFirstOrThrow()\n\n  expectAssignable<string | number>(result.avg_age)\n  expectAssignable<string | number | bigint>(result.total_people)\n  expectAssignable<number>(result.max_age)\n  expectAssignable<number>(result.min_age)\n  expectAssignable<string | number | bigint>(result.total_age)\n}\n\nasync function testSelectWithOverAndOrderByUnexpectedColumns(\n  db: Kysely<Database>,\n) {\n  const { avg, count, max, min, sum } = db.fn\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        avg('age')\n          .over((ob) => ob.orderBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        count('age')\n          .over((ob) => ob.orderBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        max('age')\n          .over((ob) => ob.orderBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        min('age')\n          .over((ob) => ob.orderBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n  expectError(\n    db\n      .selectFrom('person')\n      .select(\n        sum('age')\n          .over((ob) => ob.orderBy('no_such_column'))\n          .as('avg_age'),\n      )\n      .executeTakeFirst(),\n  )\n}\n\nasync function testSelectAsCustomFunctionArgument(db: Kysely<Database>) {\n  await db\n    .selectFrom('person')\n    .select(({ fn }) => [\n      fn('round', [fn.avg('age')]).as('avg_age'),\n      fn('round', [fn.count('age')]).as('total_people'),\n      fn('round', [fn.countAll()]).as('total_all_people'),\n      fn('round', [fn.max('age')]).as('max_age'),\n      fn('round', [fn.min('age')]).as('min_age'),\n      fn('round', [fn.sum('age')]).as('total_age'),\n    ])\n    .executeTakeFirstOrThrow()\n\n  expectError(\n    await db\n      .selectFrom('person')\n      .select(({ fn }) => [\n        fn('round', [fn.avg('NO_SUCH_COLUMN')]).as('avg_age'),\n      ])\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    await db\n      .selectFrom('person')\n      .select(({ fn }) => [\n        fn('round', [fn.count('NO_SUCH_COLUMN')]).as('avg_age'),\n      ])\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    await db\n      .selectFrom('person')\n      .select(({ fn }) => [\n        fn('round', [fn.max('NO_SUCH_COLUMN')]).as('avg_age'),\n      ])\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    await db\n      .selectFrom('person')\n      .select(({ fn }) => [\n        fn('round', [fn.min('NO_SUCH_COLUMN')]).as('avg_age'),\n      ])\n      .executeTakeFirstOrThrow(),\n  )\n\n  expectError(\n    await db\n      .selectFrom('person')\n      .select(({ fn }) => [\n        fn('round', [fn.sum('NO_SUCH_COLUMN')]).as('avg_age'),\n      ])\n      .executeTakeFirstOrThrow(),\n  )\n}\n\ninterface DB764 {\n  order: Order764\n  orderDetails: OrderDetails764\n}\n\ninterface OrderDetails764 {\n  id: Generated<string>\n  orderId: string\n  itemName: string\n  itemType: string\n  quantity: number\n  unlimited: true\n}\n\ninterface Order764 {\n  id: Generated<string>\n}\n\nenum ItemType764 {\n  FOOD = 'FOOD',\n  FEELING = 'FEELING',\n}\n\n// https://github.com/kysely-org/kysely/issues/764\nasync function testIssue764(db: Kysely<DB764>) {\n  await db\n    .with('OrderAggregates', (db) =>\n      db\n        .selectFrom('orderDetails')\n        .innerJoin('order', 'order.id', 'orderDetails.orderId')\n        .select([\n          'orderDetails.itemName',\n          'orderDetails.itemType',\n          'order.id as order_id',\n          (eb) => eb.fn.max('orderDetails.quantity').as('MaxQuantity'),\n          (eb) => eb.fn.sum('orderDetails.quantity').as('SumQuantity'),\n          (eb) =>\n            eb\n              .fn('bool_or', [eb.ref('orderDetails.unlimited')])\n              .as('AnyUnlimited'),\n        ])\n        .groupBy(['order_id']),\n    )\n    .selectFrom('OrderAggregates')\n    .select(['order_id', 'OrderAggregates.itemName'])\n    .select((eb) =>\n      eb\n        .case()\n        .when('OrderAggregates.itemType', '=', ItemType764.FOOD)\n        .then(\n          eb\n            .case()\n            .when(sql<boolean>`bool_or(${eb.ref('AnyUnlimited')})`)\n            .then(-1)\n            .else(eb.fn.max('SumQuantity'))\n            .end(),\n        )\n        .when('OrderAggregates.itemType', '=', ItemType764.FEELING)\n        .then(eb.fn.max('MaxQuantity'))\n        .else(0)\n        .end()\n        .as('totalQuantity'),\n    )\n    .groupBy([\n      'OrderAggregates.itemName',\n      'OrderAggregates.AnyUnlimited',\n      'OrderAggregates.MaxQuantity',\n      'OrderAggregates.SumQuantity',\n    ])\n    .execute()\n}\n"
  },
  {
    "path": "test/typings/test-d/alter-table.test-d.ts",
    "content": "import { expectError, expectType } from 'tsd'\nimport type { AlterTableBuilder, Kysely } from '..'\nimport type { Database } from '../shared'\nimport type { AlterTableExecutor } from '../../../dist/cjs/schema/alter-table-executor'\n\nasync function testAlterTableWithAddUniqueConstraint(db: Kysely<Database>) {\n  expectType<AlterTableBuilder>(db.schema.alterTable('test'))\n\n  expectType<AlterTableExecutor>(\n    db.schema.alterTable('test').addUniqueConstraint('a_unique', ['a']),\n  )\n\n  expectType<AlterTableExecutor>(\n    db.schema\n      .alterTable('test')\n      .addUniqueConstraint('a_unique', ['a'], (uc) => uc.nullsNotDistinct()),\n  )\n\n  expectError(\n    db.schema.alterTable('test').addUniqueConstraint('a_unique', null),\n  )\n  expectError(db.schema.alterTable('test').addUniqueConstraint('a_unique', [1]))\n  expectError(\n    db.schema\n      .alterTable('test')\n      .addUniqueConstraint(null, ['a'], (uc) => uc.nullsNotDistinct()),\n  )\n  expectError(\n    db.schema\n      .alterTable('test')\n      .addUniqueConstraint('a_unique', [1], (uc) => uc.nullsNotDistinct()),\n  )\n  expectError(\n    db.schema\n      .alterTable('test')\n      .addUniqueConstraint('a_unique', ['a'], 'wrong option'),\n  )\n}\n"
  },
  {
    "path": "test/typings/test-d/assert-type.test-d.ts",
    "content": "import type { Kysely } from '..'\nimport type { Database } from '../shared'\nimport { expectType, expectError } from 'tsd'\n\nasync function testAssertType(db: Kysely<Database>) {\n  const r1 = await db\n    .selectFrom('person')\n    .select('first_name as fn')\n    .$assertType<{ fn: string }>()\n    .executeTakeFirstOrThrow()\n\n  expectType<{ fn: string }>(r1)\n\n  const r2 = await db\n    .updateTable('person')\n    .returning('first_name as fn')\n    .$assertType<{ fn: string }>()\n    .executeTakeFirstOrThrow()\n\n  expectType<{ fn: string }>(r2)\n\n  const r3 = await db\n    .insertInto('person')\n    .values({ first_name: 'foo', age: 54, gender: 'other' })\n    .returning('first_name as fn')\n    .$assertType<{ fn: string }>()\n    .executeTakeFirstOrThrow()\n\n  expectType<{ fn: string }>(r3)\n\n  const r4 = await db\n    .deleteFrom('person')\n    .returning('first_name as fn')\n    .$assertType<{ fn: string }>()\n    .executeTakeFirstOrThrow()\n\n  expectType<{ fn: string }>(r4)\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select('first_name as fn')\n      .$assertType<{ wrong: string }>()\n      .execute(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person')\n      .select('first_name as fn')\n      .$assertType<{ fn: string; extra: number }>()\n      .execute(),\n  )\n}\n"
  },
  {
    "path": "test/typings/test-d/case.test-d.ts",
    "content": "import { expectError, expectType } from 'tsd'\nimport { type ExpressionBuilder, type ExpressionWrapper, sql } from '..'\nimport type { Database } from '../shared'\n\nasync function testCase(eb: ExpressionBuilder<Database, 'person'>) {\n  // case...when...then...when...then...end\n  expectType<ExpressionWrapper<Database, 'person', string | number | null>>(\n    eb\n      .case()\n      .when('gender', '=', 'male')\n      .then('Mr.')\n      .when('gender', '=', 'female')\n      .then(12)\n      .end(),\n  )\n\n  // case...when...then...when...then...end (as const)\n  expectType<ExpressionWrapper<Database, 'person', 'Mr.' | 12 | null>>(\n    eb\n      .case()\n      .when('gender', '=', 'male')\n      .then('Mr.' as const)\n      .when('gender', '=', 'female')\n      .then(12 as const)\n      .end(),\n  )\n\n  // case...when...then...when...then...else...end\n  expectType<ExpressionWrapper<Database, 'person', string | number | boolean>>(\n    eb\n      .case()\n      .when('gender', '=', 'male')\n      .then('Mr.')\n      .when('gender', '=', 'female')\n      .then(12)\n      .else(true)\n      .end(),\n  )\n\n  // case...when...then...when...then...else...end (as const)\n  expectType<ExpressionWrapper<Database, 'person', 'Mr.' | 12 | true>>(\n    eb\n      .case()\n      .when('gender', '=', 'male')\n      .then('Mr.' as const)\n      .when('gender', '=', 'female')\n      .then(12 as const)\n      .else(true as const)\n      .end(),\n  )\n\n  // nested case\n  expectType<\n    ExpressionWrapper<Database, 'person', 'Mr.' | 'Ms.' | 'Mrs.' | null>\n  >(\n    eb\n      .case()\n      .when('gender', '=', 'male')\n      .then('Mr.' as const)\n      .when('gender', '=', 'female')\n      .then(\n        eb\n          .case()\n          .when('marital_status', '=', 'single')\n          .then('Ms.' as const)\n          .else('Mrs.' as const)\n          .end(),\n      )\n      .end(),\n  )\n\n  // references\n  expectType<ExpressionWrapper<Database, 'person', string | number>>(\n    eb\n      .case()\n      .when('gender', '=', 'male')\n      .then(eb.ref('first_name'))\n      .else(eb.ref('age'))\n      .end(),\n  )\n\n  // expressions\n  expectType<ExpressionWrapper<Database, 'person', `Mr. ${string}` | null>>(\n    eb\n      .case()\n      .when('gender', '=', 'male')\n      .then(\n        eb.fn<`Mr. ${string}`>('concat', [\n          eb.val('Mr.'),\n          sql.lit(' '),\n          eb.ref('last_name'),\n        ]),\n      )\n      .end(),\n  )\n\n  // subquery\n  expectType<ExpressionWrapper<Database, 'person', string | null>>(\n    eb\n      .case()\n      .when('gender', '=', 'male')\n      .then(eb.selectFrom('person').select('first_name'))\n      .end(),\n  )\n\n  // errors\n\n  expectError(eb.case().when('no_such_column', '=', 'male').then('Mr.').end())\n  expectError(eb.case().when('gender', '??', 'male').then('Mr.').end())\n  expectError(eb.case().when('gender', '=', 42).then('Mr.').end())\n  expectError(eb.case().when('male').then('Mr.').end())\n}\n\nfunction testCaseValue(eb: ExpressionBuilder<Database, 'person'>) {\n  // case...value...when...then...when...then...end\n  expectType<ExpressionWrapper<Database, 'person', string | number | null>>(\n    eb.case('gender').when('male').then('Mr.').when('female').then(12).end(),\n  )\n\n  // case...value...when...then...when...then...else...end\n  expectType<ExpressionWrapper<Database, 'person', string | number | boolean>>(\n    eb\n      .case('gender')\n      .when('male')\n      .then('Mr.')\n      .when('female')\n      .then(12)\n      .else(true)\n      .end(),\n  )\n\n  // nested case\n  expectType<\n    ExpressionWrapper<Database, 'person', 'Mr.' | 'Ms.' | 'Mrs.' | null>\n  >(\n    eb\n      .case('gender')\n      .when('male')\n      .then('Mr.' as const)\n      .when('female')\n      .then(\n        eb\n          .case('marital_status')\n          .when('single')\n          .then('Ms.' as const)\n          .else('Mrs.' as const)\n          .end(),\n      )\n      .end(),\n  )\n\n  // errors\n\n  expectError(eb.case('no_such_column').when('male').then('Mr.').end())\n  expectError(eb.case('gender').when('robot').then('Mr.').end())\n  expectError(eb.case('gender').when('gender', '=', 'male').then('Mr.').end())\n}\n"
  },
  {
    "path": "test/typings/test-d/clear.test-d.ts",
    "content": "import type { Kysely } from '..'\nimport type { Database } from '../shared'\nimport { expectType } from 'tsd'\n\nasync function testClearSelect(db: Kysely<Database>) {\n  const r1 = await db\n    .selectFrom('person')\n    .select(['first_name', 'gender'])\n    .clearSelect()\n    .select('id')\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number }>(r1)\n\n  const r2 = await db\n    .selectFrom('person')\n    .selectAll()\n    .clearSelect()\n    .select('age')\n    .executeTakeFirstOrThrow()\n\n  expectType<{ age: number }>(r2)\n}\n\nasync function testClearInsert(db: Kysely<Database>) {\n  const r1 = await db\n    .insertInto('person')\n    .values({\n      first_name: 'Bruce',\n      last_name: 'Willis',\n      age: 68,\n      gender: 'male',\n    })\n    .returning(['first_name', 'gender'])\n    .clearReturning()\n    .returning('id')\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number }>(r1)\n\n  const r2 = await db\n    .insertInto('person')\n    .values({\n      first_name: 'Bruce',\n      last_name: 'Willis',\n      age: 68,\n      gender: 'male',\n    })\n    .returningAll()\n    .clearReturning()\n    .returning('age')\n    .executeTakeFirstOrThrow()\n\n  expectType<{ age: number }>(r2)\n}\n\nasync function testClearUpdate(db: Kysely<Database>) {\n  const r1 = await db\n    .updateTable('person')\n    .set({ age: 76 })\n    .where('first_name', '=', 'Arnold')\n    .returning(['first_name', 'gender'])\n    .clearReturning()\n    .returning('id')\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number }>(r1)\n\n  const r2 = await db\n    .updateTable('person')\n    .set({ age: 76 })\n    .where('first_name', '=', 'Arnold')\n    .returningAll()\n    .clearReturning()\n    .returning('age')\n    .executeTakeFirstOrThrow()\n\n  expectType<{ age: number }>(r2)\n}\n\nasync function testClearDelete(db: Kysely<Database>) {\n  const r1 = await db\n    .deleteFrom('person')\n    .where('first_name', '=', 'Bruce')\n    .returning(['first_name', 'gender'])\n    .clearReturning()\n    .returning('id')\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number }>(r1)\n\n  const r2 = await db\n    .deleteFrom('person')\n    .where('first_name', '=', 'Bruce')\n    .returningAll()\n    .clearReturning()\n    .returning('age')\n    .executeTakeFirstOrThrow()\n\n  expectType<{ age: number }>(r2)\n}\n"
  },
  {
    "path": "test/typings/test-d/coalesce.test-d.ts",
    "content": "import { expectError, expectType } from 'tsd'\nimport { type Kysely, type RawBuilder, sql } from '..'\nimport type { Database } from '../shared'\n\nasync function testCoalesceSingle(db: Kysely<Database>) {\n  const { coalesce } = db.fn\n\n  const [r0] = await db\n    .selectFrom('person')\n    .select(coalesce('age').as('age'))\n    .execute()\n  expectType<{ age: number }>(r0)\n\n  const [r1] = await db\n    .selectFrom('person')\n    .select(coalesce('last_name').as('last_name'))\n    .execute()\n  expectType<{ last_name: string | null }>(r1)\n\n  const [r2] = await db\n    .selectFrom('person')\n    .select(coalesce(db.dynamic.ref('age')).$castTo<number>().as('age'))\n    .execute()\n  expectType<{ age: number }>(r2)\n\n  const [r3] = await db\n    .selectFrom('person')\n    .select(coalesce(db.dynamic.ref('age')).as('age'))\n    .execute()\n  expectType<{ age: unknown }>(r3)\n\n  const [r4] = await db\n    .selectFrom('person')\n    .select(coalesce(value('hi!')).as('hi'))\n    .execute()\n  expectType<{ hi: string }>(r4)\n\n  const [r5] = await db\n    .selectFrom('person')\n    .select(coalesce(sql`${'hi!'}`).as('hi'))\n    .execute()\n  expectType<{ hi: unknown }>(r5)\n\n  const [r6] = await db\n    .selectFrom('person')\n    .select(coalesce(db.fn.max('age')).as('age'))\n    .groupBy('first_name')\n    .execute()\n  expectType<{ age: number }>(r6)\n\n  const [r7] = await db\n    .selectFrom('person')\n    .select(coalesce(value(null)).as('void'))\n    .execute()\n  expectType<{ void: null }>(r7)\n\n  expectError(\n    db.selectFrom('person').select(coalesce('no_such_column').as('alias')),\n  )\n\n  // no alias\n  expectError(db.selectFrom('person').select(coalesce('age')))\n}\n\nasync function testCoalesceMultiple(db: Kysely<Database>) {\n  const { coalesce } = db.fn\n\n  // number, string, Date -> number\n  const [r0] = await db\n    .selectFrom('person')\n    .select(coalesce('age', 'first_name', 'modified_at').as('field'))\n    .execute()\n  expectType<{ field: number }>(r0)\n\n  // string | null, number, Date -> string | number\n  const [r1] = await db\n    .selectFrom('person')\n    .select(coalesce('last_name', 'age', 'modified_at').as('field'))\n    .execute()\n  expectType<{ field: string | number }>(r1)\n\n  // null, string | null, string, number -> string\n  const [r2] = await db\n    .selectFrom('person')\n    .select(\n      coalesce(value(null), 'last_name', db.fn.max('first_name'), 'age').as(\n        'field',\n      ),\n    )\n    .groupBy(['last_name', 'first_name', 'age'])\n    .execute()\n  expectType<{ field: string }>(r2)\n\n  // string | null, string -> string\n  const [r3] = await db\n    .selectFrom('person')\n    .select(\n      coalesce(\n        db.fn.max<string | null>('first_name'),\n        sql<string>`${sql.lit('N/A')}`,\n      ).as('max_first_name'),\n    )\n    .execute()\n  expectType<{ max_first_name: string }>(r3)\n}\n\nfunction value<V>(value: V): RawBuilder<V> {\n  return sql`${value}`\n}\n"
  },
  {
    "path": "test/typings/test-d/create-table.test-d.ts",
    "content": "import { expectError, expectType } from 'tsd'\nimport type { CreateTableBuilder, Kysely } from '..'\nimport type { Database } from '../shared'\n\nasync function testCreateTableWithSeveralColumns(db: Kysely<Database>) {\n  expectType<CreateTableBuilder<'person'>>(db.schema.createTable('person'))\n\n  expectType<CreateTableBuilder<'person', 'a'>>(\n    db.schema.createTable('person').addColumn('a', 'varchar(255)'),\n  )\n\n  expectError(\n    db.schema\n      .createTable(1)\n      .addColumn('a', 'varchar(255)')\n      .addColumn('b', 'varchar(255)'),\n  )\n  expectError(\n    db.schema\n      .createTable('test')\n      .addColumn(null, 'varchar(255)')\n      .addColumn('b', 'varchar(255)'),\n  )\n  expectError(\n    db.schema\n      .createTable('test')\n      .addColumn('a', 'varchar(255)')\n      .addColumn('b', 'test_type'),\n  )\n}\n\nasync function testCreateTableWithAddUniqueConstraint(db: Kysely<Database>) {\n  expectType<CreateTableBuilder<'person', 'a'>>(\n    db.schema\n      .createTable('person')\n      .addColumn('a', 'varchar(255)')\n      .addUniqueConstraint('a_unique', ['a']),\n  )\n\n  expectType<CreateTableBuilder<'person', 'a'>>(\n    db.schema\n      .createTable('person')\n      .addColumn('a', 'varchar(255)')\n      .addUniqueConstraint('a_unique', ['a'], (uc) => uc.nullsNotDistinct()),\n  )\n\n  expectError(\n    db.schema\n      .createTable('test')\n      .addColumn('a', 'varchar(255)')\n      .addUniqueConstraint(1, ['a']),\n  )\n  expectError(\n    db.schema\n      .createTable('test')\n      .addColumn('a', 'varchar(255)')\n      .addUniqueConstraint('a_unique', 'test'),\n  )\n  expectError(\n    db.schema\n      .createTable('test')\n      .addColumn('a', 'varchar(255)')\n      .addUniqueConstraint('a_unique', [1]),\n  )\n  expectError(\n    db.schema\n      .createTable('test')\n      .addColumn('a', 'varchar(255)')\n      .addUniqueConstraint(null, ['a'], (uc) => uc.nullsNotDistinct()),\n  )\n  expectError(\n    db.schema\n      .createTable('test')\n      .addColumn('a', 'varchar(255)')\n      .addUniqueConstraint('a_unique', [1], (uc) => uc.nullsNotDistinct()),\n  )\n  expectError(\n    db.schema\n      .createTable('test')\n      .addColumn('a', 'varchar(255)')\n      .addUniqueConstraint('a_unique', ['a'], 'wrong option'),\n  )\n}\n\nasync function testCreateTableWithAsStatement(db: Kysely<Database>) {\n  expectError(db.schema.createTable('test').as())\n  expectError(db.schema.createTable('test').as('test'))\n}\n"
  },
  {
    "path": "test/typings/test-d/delete-query-builder.test-d.ts",
    "content": "import { expectError, expectType } from 'tsd'\nimport { type Kysely, type DeleteResult, type Selectable, sql } from '..'\nimport type { Database, Person, Pet } from '../shared'\n\nasync function testDelete(db: Kysely<Database>) {\n  const r1 = await db.deleteFrom('pet').where('id', '=', '1').executeTakeFirst()\n  expectType<DeleteResult>(r1)\n\n  const r2 = await db\n    .deleteFrom('person')\n    .using('pet')\n    .where('pet.species', '=', 'cat')\n    .executeTakeFirstOrThrow()\n  expectType<DeleteResult>(r2)\n\n  const r3 = await db\n    .deleteFrom('person')\n    .using(['pet', 'toy'])\n    .where('pet.species', '=', 'cat')\n    .executeTakeFirstOrThrow()\n  expectType<DeleteResult>(r3)\n\n  const r4 = await db\n    .deleteFrom('person')\n    .using(['person', 'pet'])\n    .innerJoin('toy', 'toy.pet_id', 'pet.id')\n    .where('pet.species', '=', 'cat')\n    .executeTakeFirstOrThrow()\n  expectType<DeleteResult>(r4)\n\n  const r5 = await db\n    .deleteFrom('person')\n    .using(['person', 'pet'])\n    .leftJoin('toy', 'toy.pet_id', 'pet.id')\n    .where('pet.species', '=', 'cat')\n    .executeTakeFirstOrThrow()\n  expectType<DeleteResult>(r5)\n\n  const r6 = await db\n    .deleteFrom(['person', 'pet'])\n    .using('person')\n    .innerJoin('pet', 'pet.owner_id', 'person.id')\n    .where('person.id', '=', 1)\n    .executeTakeFirstOrThrow()\n  expectType<DeleteResult>(r6)\n\n  const r7 = await db\n    .deleteFrom(['person', 'pet'])\n    .using('person')\n    .leftJoin('pet', 'pet.owner_id', 'person.id')\n    .where('person.id', '=', 1)\n    .executeTakeFirstOrThrow()\n  expectType<DeleteResult>(r7)\n\n  const r8 = await db\n    .deleteFrom('pet')\n    .using('person')\n    .leftJoin('pet', 'pet.owner_id', 'person.id')\n    .where('person.id', '=', 1)\n    .returningAll('person')\n    .executeTakeFirstOrThrow()\n  expectType<Selectable<Person>>(r8)\n\n  expectError(db.deleteFrom('NO_SUCH_TABLE'))\n  expectError(db.deleteFrom('pet').where('NO_SUCH_COLUMN', '=', '1'))\n  expectError(db.deleteFrom('pet').whereRef('owner_id', '=', 'NO_SUCH_COLUMN'))\n  expectError(db.deleteFrom(['pet', 'NO_SUCH_TABLE']))\n  expectError(db.deleteFrom('pet').using('NO_SUCH_TABLE'))\n  expectError(db.deleteFrom('pet').using(['pet', 'NO_SUCH_TABLE']))\n  expectError(\n    db.deleteFrom('pet').using('pet').innerJoin('NO_SUCH_TABLE', 'pet.id', 'b'),\n  )\n  expectError(\n    db\n      .deleteFrom('pet')\n      .using('pet')\n      .innerJoin('person', 'NO_SUCH_COLUMN', 'pet.owner_id'),\n  )\n  expectError(\n    db.deleteFrom('pet').using('pet').leftJoin('NO_SUCH_TABLE', 'pet.id', 'b'),\n  )\n  expectError(\n    db\n      .deleteFrom('pet')\n      .using('pet')\n      .leftJoin('person', 'NO_SUCH_COLUMN', 'pet.owner_id'),\n  )\n}\n\nasync function testReturning(db: Kysely<Database>) {\n  const r1 = await db\n    .deleteFrom('person')\n    .using(['person', 'pet'])\n    .leftJoin('toy', 'toy.pet_id', 'pet.id')\n    .where((eb) =>\n      eb.or([eb('pet.species', '=', 'cat'), eb('toy.price', '=', 0)]),\n    )\n    .returningAll('person')\n    .execute()\n  expectType<Selectable<Person>[]>(r1)\n\n  const r2 = await db\n    .deleteFrom('pet')\n    .where('pet.species', '=', 'cat')\n    .returningAll('pet')\n    .execute()\n  expectType<Selectable<Pet>[]>(r2)\n\n  const r3 = await db\n    .deleteFrom('person')\n    .using(['person', 'pet'])\n    .leftJoin('toy', 'toy.pet_id', 'pet.id')\n    .where('pet.species', '=', 'cat')\n    .returningAll(['pet', 'toy', 'person'])\n    .execute()\n  expectType<\n    {\n      id: number | string | null\n      first_name: string\n      last_name: string | null\n      age: number\n      gender: 'male' | 'female' | 'other'\n      modified_at: Date\n      marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n      deleted_at: Date | null\n\n      name: string\n      owner_id: number\n      species: 'dog' | 'cat'\n\n      price: number | null\n      pet_id: string | null\n    }[]\n  >(r3)\n\n  const r4 = await db\n    .deleteFrom('person')\n    .innerJoin('pet', 'pet.owner_id', 'person.id')\n    .where('pet.species', '=', 'dog')\n    .returningAll(['person', 'pet'])\n    .execute()\n  expectType<\n    {\n      id: number | string\n      first_name: string\n      last_name: string | null\n      age: number\n      gender: 'male' | 'female' | 'other'\n      modified_at: Date\n      marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n      deleted_at: Date | null\n\n      name: string\n      owner_id: number\n      species: 'dog' | 'cat'\n    }[]\n  >(r4)\n\n  const r5 = await db\n    .deleteFrom('pet')\n    .where('pet.species', '=', 'cat')\n    .returningAll(['pet'])\n    .execute()\n  expectType<Selectable<Pet>[]>(r5)\n\n  const r6 = await db\n    .deleteFrom('pet')\n    .where('pet.species', '=', 'dog')\n    .returningAll()\n    .execute()\n  expectType<Selectable<Pet>[]>(r6)\n\n  const r7 = await db\n    .deleteFrom('person')\n    .using(['person', 'pet'])\n    .leftJoin('toy', 'toy.pet_id', 'pet.id')\n    .where('pet.species', '=', 'cat')\n    .returningAll()\n    .execute()\n  expectType<\n    {\n      id: number | string | null\n      first_name: string\n      last_name: string | null\n      age: number\n      gender: 'male' | 'female' | 'other'\n      modified_at: Date\n      marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n      deleted_at: Date | null\n\n      name: string\n      owner_id: number\n      species: 'dog' | 'cat'\n\n      price: number | null\n      pet_id: string | null\n    }[]\n  >(r7)\n\n  const r8 = await db\n    .deleteFrom('person as p')\n    .where('p.first_name', '=', 'Jennifer')\n    .returning('p.id')\n    .executeTakeFirstOrThrow()\n  expectType<{ id: number }>(r8)\n}\n\nasync function testIf(db: Kysely<Database>) {\n  const r = await db\n    .deleteFrom('person')\n    .returning('id')\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f1'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f2'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f3'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f4'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f5'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f6'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f7'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f8'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f9'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f10'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f11'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f12'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f13'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f14'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f15'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f16'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f17'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f18'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f19'))\n    .$if(Math.random() < 0.5, (qb) => qb.returning('first_name as f20'))\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    id: number\n    f1?: string\n    f2?: string\n    f3?: string\n    f4?: string\n    f5?: string\n    f6?: string\n    f7?: string\n    f8?: string\n    f9?: string\n    f10?: string\n    f11?: string\n    f12?: string\n    f13?: string\n    f14?: string\n    f15?: string\n    f16?: string\n    f17?: string\n    f18?: string\n    f19?: string\n    f20?: string\n  }>(r)\n}\n\nasync function testOutput(db: Kysely<Database>) {\n  const r1 = await db\n    .deleteFrom('pet')\n    .outputAll('deleted')\n    .where('pet.species', '=', 'cat')\n    .execute()\n  expectType<Selectable<Pet>[]>(r1)\n\n  const r2 = await db\n    .deleteFrom('person as p')\n    .output('deleted.id')\n    .where('p.first_name', '=', 'Jennifer')\n    .executeTakeFirstOrThrow()\n  expectType<{ id: number }>(r2)\n\n  const r3 = await db\n    .deleteFrom('person as p')\n    .output(['deleted.id', 'deleted.last_name as surname'])\n    .where('p.first_name', '=', 'Jennifer')\n    .executeTakeFirstOrThrow()\n  expectType<{ id: number; surname: string | null }>(r3)\n\n  const r4 = await db\n    .deleteFrom('person')\n    .output((eb) => [\n      'deleted.age',\n      eb\n        .fn<string>('concat', [\n          eb.ref('deleted.first_name'),\n          sql.lit(' '),\n          'deleted.last_name',\n        ])\n        .as('full_name'),\n    ])\n    .where('deleted_at', '<', new Date())\n    .executeTakeFirstOrThrow()\n  expectType<{ age: number; full_name: string }>(r4)\n\n  // Non-existent column\n  expectError(db.deleteFrom('person').output('deleted.NO_SUCH_COLUMN'))\n\n  // Wrong prefix\n  expectError(db.deleteFrom('person').output('inserted.id'))\n  expectError(db.deleteFrom('person').outputAll('inserted'))\n\n  // Non-existent prefix\n  expectError(db.deleteFrom('person').output('NO_SUCH_PREFIX.id'))\n  expectError(db.deleteFrom('person').outputAll('NO_SUCH_PREFIX'))\n\n  // table prefix\n  expectError(db.deleteFrom('person').output('person.id'))\n  expectError(db.deleteFrom('person').outputAll('person'))\n\n  // No prefix\n  expectError(db.deleteFrom('person').output('id'))\n  expectError(db.deleteFrom('person').outputAll())\n}\n"
  },
  {
    "path": "test/typings/test-d/expression.test-d.ts",
    "content": "import {\n  expectAssignable,\n  expectError,\n  expectNotAssignable,\n  expectType,\n} from 'tsd'\nimport {\n  type ColumnType,\n  type Expression,\n  type ExpressionBuilder,\n  type Generated,\n  type Kysely,\n  type SqlBool,\n  expressionBuilder,\n  sql,\n} from '..'\nimport type { KyselyTypeError } from '../../../dist/cjs/util/type-error'\nimport type { Database } from '../shared'\n\nfunction testExpression(db: Kysely<Database>) {\n  const e1: Expression<number> = undefined!\n\n  expectAssignable<Expression<number>>(e1)\n  expectNotAssignable<Expression<string>>(e1)\n\n  expectAssignable<Expression<{ first_name: string }>>(\n    db.selectFrom('person').select('first_name'),\n  )\n  expectNotAssignable<Expression<{ first_name: number }>>(\n    db.selectFrom('person').select('first_name'),\n  )\n  expectNotAssignable<Expression<{ age: number }>>(\n    db.selectFrom('person').select('first_name'),\n  )\n}\n\nasync function testExpressionBuilder(\n  eb: ExpressionBuilder<Database, 'person'>,\n) {\n  // Binary expression\n  expectAssignable<Expression<number>>(eb('age', '+', 1))\n  expectAssignable<Expression<SqlBool>>(eb('age', '=', 1))\n  expectAssignable<Expression<SqlBool>>(eb('age', sql`OP`, 1))\n  expectAssignable<Expression<SqlBool>>(eb('age', sql<SqlBool>`OP`, 1))\n  expectAssignable<Expression<number>>(eb('age', sql<number>`OP`, 1))\n  expectAssignable<Expression<string>>(eb('age', sql<string>`OP`, 1))\n\n  // `not` expression\n  expectAssignable<Expression<SqlBool>>(eb.not(eb('age', '>', 10)))\n\n  // `and` expression with one item\n  expectAssignable<Expression<SqlBool>>(\n    eb.and([eb('first_name', '=', 'Jennifer')]),\n  )\n\n  // `and` expression with two items\n  expectAssignable<Expression<SqlBool>>(\n    eb.and([\n      eb('first_name', '=', 'Jennifer'),\n      eb.not(eb('last_name', '=', 'Aniston')),\n    ]),\n  )\n\n  // `or` expression with one item\n  expectAssignable<Expression<SqlBool>>(\n    eb.or([eb('first_name', '=', 'Jennifer')]),\n  )\n\n  // `or` expression with two items\n  expectAssignable<Expression<SqlBool>>(\n    eb.or([\n      eb('first_name', '=', 'Jennifer'),\n      eb.not(eb('last_name', '=', 'Aniston')),\n    ]),\n  )\n\n  // `or` chain with three items\n  expectAssignable<Expression<SqlBool>>(\n    eb('first_name', '=', 'Jennifer')\n      .or(eb.not(eb('last_name', '=', 'Aniston')))\n      .or('age', '>', 23),\n  )\n\n  // `and` chain with three items\n  expectAssignable<Expression<SqlBool>>(\n    eb('first_name', '=', 'Jennifer')\n      .and(eb.not(eb('last_name', '=', 'Aniston')))\n      .and('age', '>', 23),\n  )\n\n  // nested `and` and `or` chains.\n  expectAssignable<Expression<SqlBool>>(\n    eb.and([\n      eb('age', '=', 1).or('age', '=', 2),\n      eb('first_name', '=', 'Jennifer').or('first_name', '=', 'Arnold'),\n    ]),\n  )\n\n  expectAssignable<Expression<1>>(eb.lit(1))\n  expectAssignable<Expression<boolean>>(eb.lit(true))\n  expectAssignable<Expression<null>>(eb.lit(null))\n\n  expectAssignable<Expression<SqlBool>>(\n    eb.and({\n      'person.age': 10,\n      first_name: 'Jennifer',\n      last_name: eb.ref('first_name'),\n    }),\n  )\n\n  expectAssignable<Expression<SqlBool>>(\n    eb.or({\n      'person.age': 10,\n      first_name: 'Jennifer',\n      last_name: eb.ref('first_name'),\n    }),\n  )\n\n  expectAssignable<Expression<number | null>>(\n    eb.case().when('age', '=', 10).then(1).else(null).end(),\n  )\n\n  expectNotAssignable<Expression<number>>(\n    eb.case().when('age', '=', 10).then(1).else(null).end(),\n  )\n\n  expectAssignable<Expression<number>>(\n    eb.case().when('age', '=', 10).then(1).else(null).end().$notNull(),\n  )\n\n  expectType<\n    KyselyTypeError<'or() method can only be called on boolean expressions'>\n  >(eb('age', '+', 1).or('age', '=', 1))\n\n  expectType<\n    KyselyTypeError<'and() method can only be called on boolean expressions'>\n  >(eb('age', '+', 1).and('age', '=', 1))\n\n  // `neg` expression\n  expectAssignable<Expression<number>>(eb.neg(eb('age', '+', 10)))\n\n  // Binary expression in a comparison expression\n  expectAssignable<Expression<SqlBool>>(eb(eb('age', '+', 1), '>', 0))\n\n  // A custom function call\n  expectAssignable<Expression<string>>(eb.fn<string>('upper', ['first_name']))\n\n  expectAssignable<Expression<SqlBool>>(eb.between('age', 10, 20))\n  expectAssignable<Expression<SqlBool>>(eb.betweenSymmetric('age', 10, 20))\n\n  expectAssignable<Expression<string>>(eb.cast<string>('age', 'text'))\n  expectAssignable<Expression<string>>(eb.cast<string>(eb.ref('age'), 'text'))\n\n  expectError(eb('not_a_person_column', '=', 'Jennifer'))\n  expectError(eb('not_a_person_column', '=', 'Jennifer'))\n\n  expectError(eb.and([eb.val('not booleanish'), eb.val(true)]))\n  expectError(eb.and([eb('age', '+', 1), eb.val(true)]))\n\n  expectError(eb.or([eb.val('not booleanish'), eb.val(true)]))\n  expectError(eb.or([eb('age', '+', 1), eb.val(true)]))\n\n  expectError(eb.and({ unknown_column: 'Jennifer' }))\n  expectError(eb.and({ age: 'wrong type' }))\n\n  expectError(eb.or({ unknown_column: 'Jennifer' }))\n  expectError(eb.or({ age: 'wrong type' }))\n\n  // String literals are not allowed.\n  expectError(eb.lit('foobar'))\n\n  expectError(eb.between('age', 'wrong type', 2))\n  expectError(eb.between('age', 1, 'wrong type'))\n  expectError(eb.betweenSymmetric('age', 'wrong type', 2))\n  expectError(eb.betweenSymmetric('age', 1, 'wrong type'))\n}\n\nasync function textExpressionBuilderAny(\n  eb: ExpressionBuilder<\n    Database & {\n      actor: {\n        id: string\n        movie_earnings: number[]\n        nicknames: string[] | null\n      }\n    },\n    'actor'\n  >,\n) {\n  expectAssignable<Expression<string>>(eb.fn.any('nicknames'))\n  expectAssignable<Expression<number>>(eb.fn.any('movie_earnings'))\n  expectAssignable<Expression<number>>(eb.fn.any(eb.val([1, 2, 3])))\n\n  expectAssignable<Expression<SqlBool>>(\n    eb(eb.val('Jen'), '=', eb.fn.any('nicknames')),\n  )\n\n  expectAssignable<Expression<SqlBool>>(\n    eb(eb.val(42_000_000), '=', eb.fn.any('movie_earnings')),\n  )\n\n  expectAssignable<Expression<SqlBool>>(\n    eb(eb.val('cat'), '=', eb.fn.any(eb.selectFrom('pet').select('species'))),\n  )\n\n  // Wrong array type\n  expectError(eb(eb.val('Jen'), '=', eb.fn.any('movie_earnings')))\n\n  // Not an array\n  expectError(eb(eb.val('Jen'), '=', eb.fn.any('id')))\n}\n\nasync function testExpressionBuilderAnyWithColumnType(\n  eb: ExpressionBuilder<\n    Database & {\n      person_with_column_type: {\n        id: Generated<number>\n        ids: ColumnType<number[] | null>\n        names: ColumnType<string[], never, string[]>\n        regular_array: number[]\n      }\n    },\n    'person_with_column_type'\n  >,\n) {\n  expectAssignable<Expression<number>>(eb.fn.any('ids'))\n  expectAssignable<Expression<string>>(eb.fn.any('names'))\n  expectAssignable<Expression<number>>(eb.fn.any('regular_array'))\n\n  // Should work in where clauses\n  expectAssignable<Expression<SqlBool>>(eb(eb.val(42), '=', eb.fn.any('ids')))\n  expectAssignable<Expression<SqlBool>>(\n    eb(eb.val('test'), '=', eb.fn.any('names')),\n  )\n}\n\nfunction testExpressionBuilderTuple(db: Kysely<Database>) {\n  db.selectFrom('person')\n    .selectAll()\n    .where(({ eb, refTuple, tuple }) =>\n      eb(refTuple('first_name', 'last_name'), 'in', [\n        tuple('Jennifer', 'Aniston'),\n        tuple('Sylvester', 'Stallone'),\n      ]),\n    )\n\n  db.selectFrom('person')\n    .selectAll()\n    .where(({ eb, refTuple, selectFrom }) =>\n      eb(\n        refTuple('first_name', 'last_name'),\n        'in',\n        selectFrom('person')\n          .select(['first_name', 'last_name'])\n          .$asTuple('first_name', 'last_name'),\n      ),\n    )\n\n  // Wrong tuple type\n  expectError(\n    db\n      .selectFrom('person')\n      .where(({ eb, refTuple, tuple }) =>\n        eb(refTuple('first_name', 'last_name'), 'in', [\n          tuple('Jennifer', 'Aniston'),\n          tuple('Sylvester', 1),\n        ]),\n      ),\n  )\n\n  // Wrong tuple length\n  expectError(\n    db\n      .selectFrom('person')\n      .where(({ eb, refTuple, tuple }) =>\n        eb(refTuple('first_name', 'last_name'), 'in', [\n          tuple('Jennifer', 'Aniston', 'Extra'),\n          tuple('Sylvester', 'Stallone'),\n        ]),\n      ),\n  )\n\n  // Not all selected columns provided for $asTuple\n  expectType<\n    KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'>\n  >(\n    db\n      .selectFrom('person')\n      .select(['first_name', 'last_name', 'age'])\n      .$asTuple('first_name', 'last_name'),\n  )\n\n  // Duplicate column provided for $asTuple\n  expectError(\n    db\n      .selectFrom('person')\n      .select(['first_name', 'last_name'])\n      .$asTuple('first_name', 'last_name', 'last_name'),\n  )\n}\n\nfunction testExpressionBuilderConstructor(db: Kysely<Database>) {\n  const eb1 = expressionBuilder<Database, 'person'>()\n  expectType<ExpressionBuilder<Database, 'person'>>(eb1)\n\n  const eb2 = expressionBuilder<Database>()\n  expectType<ExpressionBuilder<Database, never>>(eb2)\n\n  const eb3 = expressionBuilder(\n    db.selectFrom('action').innerJoin('pet', (join) => join.onTrue()),\n  )\n  expectType<ExpressionBuilder<Database, 'action' | 'pet'>>(eb3)\n}\n"
  },
  {
    "path": "test/typings/test-d/generic-pre-5.4.test-d.ts",
    "content": "import type {\n  Kysely,\n  ExpressionBuilder,\n  SelectQueryBuilder,\n  Generated,\n  Nullable,\n  SelectType,\n} from '..'\n\nimport { expectAssignable, expectType } from 'tsd'\nimport type { Database } from '../shared'\n\n// TODO: type-checking this is crazy slow. Figure out the cause.\nfunction testSelectQueryBuilderExtends() {\n  type A = { a: number }\n  type B = { b: string }\n\n  type T1 = SelectQueryBuilder<{ a: A }, 'a', unknown>\n\n  // This type extends T1 and should be assignable to it.\n  type T2 = SelectQueryBuilder<{ a: A; b: B }, 'a' | 'b', { a: number }>\n\n  const t2 = {} as T2\n  expectAssignable<T1>(t2)\n}\n\n// TODO: type-checking this is crazy slow. Figure out the cause.\nfunction testExpressionBuilderExtends() {\n  type A = { a: number }\n  type B = { b: string }\n\n  type T1 = ExpressionBuilder<{ a: A }, 'a'>\n\n  // This type extends T1 and should be assignable to it.\n  type T2 = ExpressionBuilder<{ a: A; b: B }, 'a' | 'b'>\n\n  const t2 = {} as T2\n  expectAssignable<T1>(t2)\n}\n\n// TODO: type-checking this is crazy slow. Figure out the cause.\nfunction testExpressionBuilderExtendsFuncArg() {\n  type A = { a: number }\n  type B = { b: string }\n  type C = { c: boolean }\n\n  // This type extends T1 and should be assignable to it.\n  type T2 = ExpressionBuilder<{ a: A; b: B; c: C }, 'a' | 'b' | 'c'>\n\n  function test(eb: ExpressionBuilder<{ a: A; b: B; c: C }, 'b' | 'c'>) {\n    console.log(eb)\n  }\n\n  const t2 = {} as T2\n  test(t2)\n}\n\n// TODO: type-checking this is crazy slow. Figure out the cause.\nasync function testGenericSelectHelper() {\n  type Parent = { id: Generated<string> }\n  type Person = { id: Generated<string>; parent_id: string }\n  type Pet = { owner_id: string; name: string }\n  const db: Kysely<{ person: Person; parent: Parent; pet: Pet }> = undefined!\n\n  function personPetSelect(\n    eb: ExpressionBuilder<\n      {\n        parent: Nullable<Pick<Parent, 'id'>>\n        petJoin: Nullable<Pick<Pet, 'owner_id'>>\n      },\n      'parent' | 'petJoin'\n    >,\n  ) {\n    return ['parent.id'] as const\n  }\n\n  const result = await db\n    .selectFrom('parent')\n    .leftJoin('person as personJoin', 'personJoin.parent_id', 'parent.id')\n    .leftJoin('pet as petJoin', 'petJoin.owner_id', 'personJoin.id')\n    .select(personPetSelect)\n    .execute()\n}\n\nasync function testSelectsInVariable(db: Kysely<Database>) {\n  const selects = [\n    'first_name',\n    (eb: ExpressionBuilder<Database, 'person'>) =>\n      eb\n        .selectFrom('pet')\n        .select('name')\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .as('pet_name'),\n  ] as const\n\n  const r1 = await db\n    .selectFrom('person')\n    .select(selects)\n    .executeTakeFirstOrThrow()\n\n  expectType<{ first_name: string; pet_name: string | null }>(r1)\n}\n\nasync function testSelectFromDynamic(db: Kysely<Database>) {\n  const r1 = await getIdDynamic(db, 'person')\n  expectType<{ id: number | string }>(r1)\n\n  const r2 = await getIdDynamic(db, 'pet')\n  expectType<{ id: number | string }>(r2)\n\n  const r3 = await getRowDynamic(db, 'movie')\n  expectType<{ id: number | string }>(r3)\n\n  const r4 = await getRowDynamic(db, 'person')\n  expectType<{ id: number | string }>(r4)\n\n  const r5 = await getRowByColumnDynamic(db, 'person', 'first_name', 'Jennifer')\n  expectType<{ id: number | string }>(r5)\n}\n\nasync function getIdDynamic<T extends 'person' | 'pet'>(\n  db: Kysely<Database>,\n  t: T,\n) {\n  const { table } = db.dynamic\n\n  return await db\n    .selectFrom(table<'person' | 'pet'>(t).as('t'))\n    .select('t.id')\n    .executeTakeFirstOrThrow()\n}\n\nasync function getRowDynamic<T extends keyof Database>(\n  db: Kysely<Database>,\n  t: T,\n) {\n  const { table } = db.dynamic\n\n  return await db\n    .selectFrom(table<keyof Database>(t).as('t'))\n    .selectAll('t')\n    .executeTakeFirstOrThrow()\n}\n\nasync function getRowByIdDynamic<\n  T extends keyof Database,\n  ID extends SelectType<Database[T]['id']>,\n>(db: Kysely<Database>, t: T, id: ID) {\n  const { table } = db.dynamic\n\n  return await db\n    .selectFrom(table<keyof Database>(t).as('t'))\n    .selectAll('t')\n    .where('id', '=', id as any)\n    .executeTakeFirstOrThrow()\n}\n\nasync function getRowByColumnDynamic<\n  T extends keyof Database,\n  C extends keyof Database[T] & string,\n  V extends SelectType<Database[T][C]>,\n>(db: Kysely<Database>, t: T, c: C, v: V) {\n  const { table, ref } = db.dynamic\n\n  return await db\n    .selectFrom(table<keyof Database>(t).as('t'))\n    .selectAll()\n    .where(ref<keyof Database[keyof Database] & string>(c), '=', v)\n    .orderBy('t.id')\n    .executeTakeFirstOrThrow()\n}\n"
  },
  {
    "path": "test/typings/test-d/generic.test-d.ts",
    "content": "import type {\n  Kysely,\n  ExpressionBuilder,\n  SelectQueryBuilder,\n  Generated,\n  Nullable,\n  Selectable,\n  SelectType,\n} from '..'\n\nimport { expectAssignable, expectType } from 'tsd'\nimport type { Database, Movie, Person } from '../shared'\n\n// TODO: type-checking this is crazy slow. Figure out the cause.\nfunction testSelectQueryBuilderExtends() {\n  type A = { a: number }\n  type B = { b: string }\n\n  type T1 = SelectQueryBuilder<{ a: A }, 'a', unknown>\n\n  // This type extends T1 and should be assignable to it.\n  type T2 = SelectQueryBuilder<{ a: A; b: B }, 'a' | 'b', { a: number }>\n\n  const t2 = {} as T2\n  expectAssignable<T1>(t2)\n}\n\n// TODO: type-checking this is crazy slow. Figure out the cause.\nfunction testExpressionBuilderExtends() {\n  type A = { a: number }\n  type B = { b: string }\n\n  type T1 = ExpressionBuilder<{ a: A }, 'a'>\n\n  // This type extends T1 and should be assignable to it.\n  type T2 = ExpressionBuilder<{ a: A; b: B }, 'a' | 'b'>\n\n  const t2 = {} as T2\n  expectAssignable<T1>(t2)\n}\n\n// TODO: type-checking this is crazy slow. Figure out the cause.\nfunction testExpressionBuilderExtendsFuncArg() {\n  type A = { a: number }\n  type B = { b: string }\n  type C = { c: boolean }\n\n  // This type extends T1 and should be assignable to it.\n  type T2 = ExpressionBuilder<{ a: A; b: B; c: C }, 'a' | 'b' | 'c'>\n\n  function test(eb: ExpressionBuilder<{ a: A; b: B; c: C }, 'b' | 'c'>) {\n    console.log(eb)\n  }\n\n  const t2 = {} as T2\n  test(t2)\n}\n\n// TODO: type-checking this is crazy slow. Figure out the cause.\nasync function testGenericSelectHelper() {\n  type Parent = { id: Generated<string> }\n  type Person = { id: Generated<string>; parent_id: string }\n  type Pet = { owner_id: string; name: string }\n  const db: Kysely<{ person: Person; parent: Parent; pet: Pet }> = undefined!\n\n  function personPetSelect(\n    eb: ExpressionBuilder<\n      {\n        parent: Nullable<Pick<Parent, 'id'>>\n        petJoin: Nullable<Pick<Pet, 'owner_id'>>\n      },\n      'parent' | 'petJoin'\n    >,\n  ) {\n    return ['parent.id'] as const\n  }\n\n  const result = await db\n    .selectFrom('parent')\n    .leftJoin('person as personJoin', 'personJoin.parent_id', 'parent.id')\n    .leftJoin('pet as petJoin', 'petJoin.owner_id', 'personJoin.id')\n    .select(personPetSelect)\n    .execute()\n}\n\nasync function testSelectsInVariable(db: Kysely<Database>) {\n  const selects = [\n    'first_name',\n    (eb: ExpressionBuilder<Database, 'person'>) =>\n      eb\n        .selectFrom('pet')\n        .select('name')\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .as('pet_name'),\n  ] as const\n\n  const r1 = await db\n    .selectFrom('person')\n    .select(selects)\n    .executeTakeFirstOrThrow()\n\n  expectType<{ first_name: string; pet_name: string | null }>(r1)\n}\n\nasync function testSelectFromDynamic(db: Kysely<Database>) {\n  const r1 = await getIdDynamic(db, 'person')\n  expectType<{ id: number }>(r1)\n\n  const r2 = await getIdDynamic(db, 'pet')\n  expectType<{ id: string }>(r2)\n\n  const r3 = await getRowDynamic(db, 'movie')\n  expectType<Selectable<Movie>>(r3)\n\n  const r4 = await getRowDynamic(db, 'person')\n  expectType<Selectable<Person>>(r4)\n\n  const r5 = await getRowByColumnDynamic(db, 'person', 'first_name', 'Jennifer')\n  expectType<Selectable<Person>>(r5)\n}\n\nasync function getIdDynamic<T extends 'person' | 'pet'>(\n  db: Kysely<Database>,\n  t: T,\n) {\n  const { table } = db.dynamic\n\n  return await db\n    .selectFrom(table(t).as('t'))\n    .select('t.id')\n    .executeTakeFirstOrThrow()\n}\n\nasync function getRowDynamic<T extends keyof Database>(\n  db: Kysely<Database>,\n  t: T,\n) {\n  const { table } = db.dynamic\n\n  return await db\n    .selectFrom(table(t).as('t'))\n    .selectAll('t')\n    .executeTakeFirstOrThrow()\n}\n\nasync function getRowByIdDynamic<\n  T extends keyof Database,\n  ID extends SelectType<Database[T]['id']>,\n>(db: Kysely<Database>, t: T, id: ID) {\n  const { table } = db.dynamic\n\n  return await db\n    .selectFrom(table(t).as('t'))\n    .selectAll('t')\n    .where('id', '=', id as any)\n    .executeTakeFirstOrThrow()\n}\n\nasync function getRowByColumnDynamic<\n  T extends keyof Database,\n  C extends keyof Database[T] & string,\n  V extends SelectType<Database[T][C]>,\n>(db: Kysely<Database>, t: T, c: C, v: V) {\n  const { table, ref } = db.dynamic\n\n  return await db\n    .selectFrom(table(t).as('t'))\n    .selectAll()\n    .where(ref(c), '=', v)\n    .orderBy('t.id')\n    .executeTakeFirstOrThrow()\n}\n"
  },
  {
    "path": "test/typings/test-d/huge-db.test-d.ts",
    "content": "/**\n * This file is more of a performance test. The tests in this file will become\n * extremely slow if type performance regressions are introduced to the codebase.\n */\n\nimport { expectError } from 'tsd'\nimport type { ColumnType, Kysely } from '..'\n\nexport type Decimal = ColumnType<string, number | string, number | string>\n\nexport type Generated<T> =\n  T extends ColumnType<infer S, infer I, infer U>\n    ? ColumnType<S, I | undefined, U>\n    : ColumnType<T, T | undefined, T>\n\nexport interface Table0ec723c3d4ee7229ffba2a11539b0129 {\n  col_4ea20fbed0c11321d0d5e8c50873ad43: number\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tablec67d8be002857dd3a70a2c4edaa4671a {\n  col_869cdfb59eef781ebd6a3b78e43344e6: Generated<string | null>\n  col_b8a21c4934fdc0366222c19c14b9e1b9: Generated<string | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_33cee772b203aed80ee06d3dcb2cbcd0: Generated<number | null>\n  id: Generated<number>\n  col_40cee1e4d1c6b882095d5d343de8a0e2: Generated<number | null>\n  col_458d5f1afc81ae7291a7aaad852dc12a: Generated<string | null>\n  col_aeffdc77f4dde5fd265842bc848e92d1: Generated<number | null>\n  col_105b287b6f42e3e08bccae5fa0bc1e57: Generated<number | null>\n  col_b53dab55eaeda66574268ffea2dd4da0: Generated<string | null>\n  col_0e46a6ad6b83de719c1b5b777e48c8c5: Generated<string | null>\n  col_aff776838092862d398b58e380901753: Generated<number | null>\n}\n\nexport interface Table3face097074d5d4ea47610accdd3ffc1 {\n  col_7d5c32a33ff432c746e4d4e37423df3a: string\n  col_b4e2525113738f1ed80758dbdfc77c51: string\n  col_d62f4d956a18fd3eec07e560acd55b59: number\n  col_f32428508672211d04f041977bc90510: number\n  col_072e823de1daac617e83074311b89962: string\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tableed617265d2d72c8e748ff8796bfa04c4 {\n  col_d9bc3ceaea0dddd80b93a2b5c5a7f827: number\n  col_3b04aeab47e304b0ae167274f324d5d3: string\n  col_b4e2525113738f1ed80758dbdfc77c51: string\n  col_7213e317986c96016a753182775fc7e0: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n}\n\nexport interface Table6dc0e4bf3b08bdf7391e5d833d1673d6 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_4ab5b1dd04a8cefd62107890b80103cd: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table2f01d1d7b29ae047871b62964df1ecc3 {\n  col_2ba95af0fa085c5e3cc3a55e48532985: number\n  col_7426b7174c1b7d22061329a60b94e63f: number\n  id: Generated<number>\n}\n\nexport interface Table9f50dbe0b662b9cea0d016836eb72504 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table4b8e90e811d962e132f9550bc90d5443 {\n  col_869cdfb59eef781ebd6a3b78e43344e6: Generated<string | null>\n  col_33cee772b203aed80ee06d3dcb2cbcd0: Generated<number | null>\n  id: Generated<number>\n  col_40cee1e4d1c6b882095d5d343de8a0e2: Generated<number | null>\n  col_458d5f1afc81ae7291a7aaad852dc12a: Generated<string | null>\n  col_aeffdc77f4dde5fd265842bc848e92d1: Generated<number | null>\n  col_105b287b6f42e3e08bccae5fa0bc1e57: Generated<number | null>\n}\n\nexport interface Table0ae6c699b7b44b166093c052150a0d36 {\n  col_0dc6bca1e7fe092ff816894c1f2fcada: Generated<string>\n  col_3f706bc8748ebe9b1edfcb4e2e03e4c5: Generated<string>\n  col_e6892b0d5da4a0f546f52b29d82aab71: Generated<string>\n  col_09d498d9fabfec1c421acb34c996c0f2: number\n  col_78a802ff9c1d651d6a168acdf039c4a7: number\n  id: Generated<number>\n}\n\nexport interface Table2e45370c867ddf8f0ca7710b63dd2746 {\n  col_5e9ee2aa243c91c65fbf94a31806496d: string\n  col_7db3960deab1cd20d8b5b1f5501f3987: number\n  id: Generated<number>\n  col_910c87c70d93d69a64538ffc358a99de: 'detalle' | 'referencias'\n}\n\nexport interface Table19f57540d944441abc6dcebc976adf96 {\n  col_5e9ee2aa243c91c65fbf94a31806496d: string\n  col_603225ce2d6e2ff429bde293c04ad734: number\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table1d1b84f13a74383d5b0324a011b609c6 {\n  col_bca1167f466e892a6e32edf82abd97bf: number\n  col_0edb7526b7143126ccfb957dd13caaeb: number\n  col_f9c22b71f730f5257411ff5461646fe8: number\n  col_e439bf701f76b768053c59bd57f81f7b: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: Generated<number | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n}\n\nexport interface Table42dbaa8105cb92599360aa5169283403 {\n  col_bca1167f466e892a6e32edf82abd97bf: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_b1dc1e3377a082304d817664243e7b17: Generated<string | null>\n}\n\nexport interface Table2f81c25612f8fefd026b753a1753974a {\n  col_f9c22b71f730f5257411ff5461646fe8: Generated<number | null>\n  col_6ccc67f5bce269cfd6973525010692a0: Generated<number | null>\n  col_fb56864b5d334395e35ec45174902736: number\n  col_d812f85f291b30d4782f9accdc973515: number\n  col_fb3c6ec7d586e24e823cb17a11e0de45: Generated<number | null>\n  col_a538a4b49163b8abcdcff07958d6290c: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_33cee772b203aed80ee06d3dcb2cbcd0: Generated<number | null>\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fed6fd6b4a682868e85af10ef151f374: Generated<string | null>\n}\n\nexport interface Tableded2bdb12664e58a26152ebb5fe676bb {\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: Generated<string | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_41bad005d542c027f208773d3f0f4a28: number\n}\n\nexport interface Table1c765aad5af6c98fb0ef475fadda911b {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: Generated<number>\n  col_f9c22b71f730f5257411ff5461646fe8: number\n  col_6ccc67f5bce269cfd6973525010692a0: Generated<number | null>\n  col_fb3c6ec7d586e24e823cb17a11e0de45: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n}\n\nexport interface Table23e7a1e5ab953d2a85a5958458d0d824 {\n  col_fb3c6ec7d586e24e823cb17a11e0de45: number\n  col_3d54e846d74728347124d4872f3d61b4: Generated<string | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: Generated<string | null>\n  col_b114935b452a2d927bd5ac81ad9a3d67: Generated<string | null>\n  col_910c87c70d93d69a64538ffc358a99de: Generated<string | null>\n  col_41bad005d542c027f208773d3f0f4a28: number\n}\n\nexport interface Table41bb6a93b802fe08f0b054ae835e2fe4 {\n  col_603225ce2d6e2ff429bde293c04ad734: number\n  col_f9c22b71f730f5257411ff5461646fe8: number\n  id: Generated<number>\n}\n\nexport interface Table8be6c29eada2e2ef68bef0c9c1401a97 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: Generated<number | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_c37d5771c5258f10ea31baab67cba178: Generated<number | null>\n}\n\nexport interface Tablee91e54a2c273ec3221b4d98ae8d79d12 {\n  col_c7062aaaa576936166196ab3c2e3342d: number\n  col_4ddfa5e839c6a6dacce57d66df206943: number\n  id: Generated<number>\n}\n\nexport interface Tablebb08e5d0fa8fd6089eeeb1ba950944a1 {\n  col_d08c3aaad1d4c926a4bf283098fcc325: Generated<string | null>\n  col_fb56864b5d334395e35ec45174902736: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_249c850f62ea50feb918b095fc56d763: Generated<string | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablecaf406ab258ff4b54413265206d55b45 {\n  col_f9c22b71f730f5257411ff5461646fe8: number\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_95a573b127ca2c23a2ed1dbc7d03d29e: string\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date>\n}\n\nexport interface Table90ffcbc2bfc57b68acac037b0aeae3d4 {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: Generated<number>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: Generated<string | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_15e729f544f76d3d0ad6bc3de492f077: string\n}\n\nexport interface Table1e2c9919a848fb2673ac28780aba041c {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_50cbd0336a73919113afcca87d9d1e48: string\n}\n\nexport interface Table4f240fba2b420e220c97e6e14c4819c6 {\n  col_869cdfb59eef781ebd6a3b78e43344e6: Generated<string | null>\n  col_1d9d9279776c5549212200cb14336162: Generated<string | null>\n  col_74bf7a1e74042c7a207b4e4d6144b8a1: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_4f84013a8b5e4c2b7529058c8fafcaa8: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_c55b5208e65984aac86ada39165d9d62: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_1f6eddf77651742ff1d83404930b09ae: string\n  col_ef1e84bf5d70755290854b1d0d60c91f: string\n  col_8b5da04bf1aacd462ab37eec2f0dea98: string\n  col_3917508388f24a50271f7088b657123c: Generated<string | null>\n  col_eb6047359d3711dac3175270345f5c3b: string\n  col_0169235b1b604520a263cfa57a00b7a2: Generated<number>\n}\n\nexport interface Tablec97e3cdd896ff553853d7817e4a866e2 {\n  col_08b4d026d42ae768f63552c6de119d71: Generated<string | null>\n  col_066a120fe3abe924fdd105d2073b3a64: Generated<number | null>\n  col_a4effcb9a007ae19664a1e3b0704e92f: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_555511eb2ff60ace56c0128985d10cb5: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_35772ed8414e25ad46fc4b92e07853a2: Generated<number | null>\n  col_4a7f3834f24f1c5e95aded0726c807e2: Date\n  col_8f4a31364a65a9f539032a16e3f4ea8b: Date\n  col_ff9d87789325c168e0e8272e8d138a21: Generated<Date | null>\n  col_7a9cd04d755a1c1f269ce7184b943521: Date\n  col_7426b7174c1b7d22061329a60b94e63f: number\n  id: Generated<number>\n  col_aac430b49cc975fb51fed9e6d9856548: Generated<number | null>\n  col_2cf1ecc054fac526249f379db15f6114: number\n  col_89addf722cc48ff1df7954f97e20b10b: Generated<string | null>\n  col_2fc68d3ca47f71df3c84961997e28d69: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_0191c0aa0d39de591b5236b304496123: number\n  col_f230bd30a85e2ec6bc2da7b727544ed6: number\n  col_f609bfdeed2c51dbb142fd03bddfd02a: number\n  col_2c4a4b433aedea3b93e0243fba4062f2: number\n  col_080cbfe43a25572bb2a66634b6d5dce8: number\n  col_5c63e943a6e825630ccaefcbed7a719b: number\n  col_a615c4f966221bfcfb8eac6397f4562e: number\n  col_a6925a86b76a07e17077ffd5f2990e7b: number\n  col_83750383555947e4ccbd9661a0948ffe: number\n  col_5c82df9ac5a4aec30ad4eb89769fbcd8: number\n  col_4ca76cee384ffac98c8a3e3c8a61bfeb: number\n  col_95b1eb6ceb5082a8b459a4722417922d: number\n  col_7d39847d54a6fc52735c6a250cfce5eb: string\n  col_345e4aa36e0fb44379bce371c87b70f4: Generated<string | null>\n  col_910c87c70d93d69a64538ffc358a99de: number\n  col_3356a84dafce383906e79fffee87d8bf: Generated<string | null>\n  col_b14411549804e01414d6ad1481680844: Generated<string | null>\n  col_270d34ae82d8c18c7b46e83fd3556a59: Generated<string | null>\n  col_9abb4592b230f6a6fa4214f5d86aaa4d: Generated<string | null>\n  col_d512407d4f684d1284b36763038e0ed3: Generated<string | null>\n  col_9b4ca322bec71dd7f0296cef261ae8ec: Generated<string | null>\n  col_0aff87eb8d3d48fa89e873060f0715d4: Generated<string | null>\n}\n\nexport interface Table4974bbdf9d728fb538d7507cb9f84842 {\n  col_77df54ec5f2bfd959a54c423b59c0d38: number\n  id: Generated<number>\n  col_ee96bf5f8ef3f927a1a7fc723df4cd90: number\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n}\n\nexport interface Tablea3c8286fc7df926fbf05e09a03e2ac77 {\n  col_77df54ec5f2bfd959a54c423b59c0d38: number\n  id: Generated<number>\n  col_ee96bf5f8ef3f927a1a7fc723df4cd90: number\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n}\n\nexport interface Table39bdacc8b55267ffc8bf75ff8ec564ce {\n  col_fee6d937834161cc73b3698fee871f5c: string\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_9b0c62311c53c898ce6699696d685a14: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_95a573b127ca2c23a2ed1dbc7d03d29e: string\n  col_8f4a31364a65a9f539032a16e3f4ea8b: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_25980343ed3b4c231a154e5e88396938: number\n  col_fb1ecce130681efa10fd55197773267d: number\n  col_d8ad55006c0efc8437cc487b5c5459f6: number\n  col_01abc2f9e295923216e8462e3a88bf5d: string\n  col_89ea1e31584f13b90dfa66a76569e69c: string\n  col_ea7e482493b72c75cf90057ba252352b: number\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n  col_f8b0d195967998d8afabe1b39912ae34: string\n  col_ac339ab9133743c084a804cc83010c7a: string\n}\n\nexport interface Table3d68aac4deb5f76aaffa0df8c01e305a {\n  col_c50368ae5e839e9224eb0947f06fc605: number\n  col_a9564ebc3289b7a14551baf8ad5ec60a: Date\n  id: Generated<number>\n  col_a7f4797b61012da3a9c1a8049c8a4974: number\n}\n\nexport interface Table90a64fc3cea5bc905374973771cafcd3 {\n  col_764a70ee8bb195d3475253200bf2e297: number\n  col_80ae6f72f9c170f9e1bcae48c1677802: number\n  id: Generated<number>\n}\n\nexport interface Tablec479a580bb37024884d940eeacc9c4aa {\n  col_764a70ee8bb195d3475253200bf2e297: number\n  id: Generated<number>\n  col_b2211a70f2ff7369336027ed47f18f7f: number\n}\n\nexport interface Table1d62a6c4a9763009cda042181b0c48af {\n  col_bd4e67d8c3f68e4b7117a7a88e22b287: string\n  id: Generated<number>\n  col_e245eb517472187d10441eca2c4a9aeb: number\n}\n\nexport interface Table916f65bd1433290f26613ccd976c68a7 {\n  col_0c22ebe1ceea12bbe3dade54d797497d: number\n  id: Generated<number>\n  col_53f18391d7b465f6918d73498af5abf0: string\n  col_bfd8f7ddc31266f25afd1b6ea43d8750: number\n  col_b9091a846b34e0fac6de153fa4634c7b: Generated<number>\n  col_0e46a6ad6b83de719c1b5b777e48c8c5: string\n}\n\nexport interface Tabledb34593d7377d2007d44ba4b47dcec97 {\n  col_08de056b6d3139a95d0aaf99f8e3c52e: number\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  id: Generated<number>\n}\n\nexport interface Tablef7d7a7557d9db50bd40fe14bd830b9d4 {\n  col_25cd93f430d277509b60d4390636895f: string\n  col_352ea8d15082ec4cd9b5ffb25fc99c71: number\n  col_6d210c02b9f9e0fd7c6bb98e4b23d240: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: number\n  col_46e6bd185eb3c01ad5692d9ab01733b8: number\n  col_26286361ce53d0207945814927712ac2: number\n  col_2245275cb6562821fd22d2523a2667e8: Date\n  col_955e7ed9557ee9c44c59bf005ea23d2d: Date\n  col_1139ca108352fe62c38518aeb04c824d: string\n  col_699b1539895a99ae5b9de4f5e8006d7c: Generated<number | null>\n  col_189501ea5ae0d0ec760d5848ef9b58e4: number\n}\n\nexport interface Table309c66af6ff8ccb2dcf123e1af40c9c4 {\n  col_821c248ea5f31b36e1fef43cbcf38495: number\n  col_49a7abbdc564bf92a27c31a936047cda: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  col_c6080ec65b20eed8dd083f2ae705fd28: string\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_1f98c1057055738f2125180731cb2d39: number\n  col_1d119125897e514751e695fab638cf81: number\n  col_ed9d312bfff3b171743cff4aa1954294: number\n}\n\nexport interface Table8921b63f9cb21e8293a8c1ddd9edc866 {\n  col_0a3a5156d1abf43e019d933129cf1d3d: number\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table2037e68416ae40369fba0a939e7ac693 {\n  col_6137cde4893c59f76f005a8123d8e8e6: Generated<string | null>\n  col_a7743b12384fd798fdad7bff9e75bee3: Generated<number | null>\n  id: Generated<string>\n}\n\nexport interface Table2b3f160083004c6c92a2ce1faf87067d {\n  col_25cd93f430d277509b60d4390636895f: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_62bd695be89e0f07c72268b40df9c2db: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_34e7aea5cf0f74ee76b3f5445a3ac1cf: Date\n  col_c84d2025f9e13529cf7b4aa05275bdf6: Date\n  id: Generated<number>\n  col_2fd6a67502ba2fc6e63b23903522d93b: Generated<number | null>\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n  col_97ec9689eca8dace826b37d2ed59250b: number\n  col_3f9be60473c4a309579563a7358c92f8: number\n  col_910c87c70d93d69a64538ffc358a99de: string\n  col_07b01206d9860575d30d3b2bdc4ef8b8: number\n  col_6200d8f84ce77a52a86aecf31d7ac101: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table5135075fea7b2d1c93603df216620907 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_47800dcca216b1b165c13199d66c3b63: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_e7fa32cb05ba9ddc8d5f75bdf1694790: string\n}\n\nexport interface Table5d4433ff31ef75511e70aa6e71495afe {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table9e258b1708bd64e877d6cca1467dee66 {\n  col_821c248ea5f31b36e1fef43cbcf38495: number\n  col_8a79872b2fd9eca20ec1e0823abe36fa: Generated<string>\n  col_8ba45d6c9fbc6997e452dc62a60c32aa: Generated<string>\n  col_66dc451da6180c375f5eccf6a178abbe: Generated<number | null>\n  col_4a375049db156d117c5ad35214dfe424: number\n  col_535325947cf44473a2c18fad07fe9457: Generated<number | null>\n  col_49a7abbdc564bf92a27c31a936047cda: number\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_50d92f9a5774b1f89abbbc4ac7f546f0: Generated<string>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_62bd695be89e0f07c72268b40df9c2db: number\n  col_cc9b81b3318668e7bd040b871602eafd: Generated<string>\n  col_970dbef257f683fb01a38f38a4086cc5: Generated<string>\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_4649c587e02b1a41f7eb4967032e10c3: Generated<string | null>\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  col_60c9259051ec33ce67fb8dbca8cc0a49: Generated<number>\n  id: Generated<number>\n  col_e923cd6ce39f1ad88fcf58e070574612: Generated<string>\n  col_6fcadaf6349923a75d54632571ccec9d: Generated<string>\n  col_e1dfc335e98f95a54ebb2a3335b71817: Generated<number | null>\n  col_a5846a54856ff3e7e3427506de9f791c: Generated<number | null>\n  col_a846adea5ee689d2a11a692bafbc2dae: Generated<Date | null>\n  col_50eed02f38aae94f07e41395a64cf64b: Generated<string>\n  col_5b75dbfc85a5e0870a34cc3bfa2cf2ae: Generated<string>\n  col_2700d8a25d8d8e80c4ad5b622ea5dbec: number\n  col_7d39847d54a6fc52735c6a250cfce5eb: Generated<string>\n  col_53a208b112254787b9ebe57338d2e92a: Generated<Decimal>\n  col_8f986281fe440bb551e6baa8d3ed2a28: Generated<number>\n  col_7f4c1276d300132fccd6f6d32ccb3002: Generated<number | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: Generated<number | null>\n  col_d849e38a75aa2b36a69eff901e6af371: Generated<'auto' | 'validado'>\n}\n\nexport interface Table4ed17d356988e97fe63e4b4e3b060917 {\n  col_2e6b22e3aeade4be1854aa4191f7b786: number\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_1ba1f915f54c8d29d5766cc9b0efe0f2: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablea95d291bccf0be8becb18282bcbf93a9 {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_9dd1bc5c639dd9f27a30853ccf20cf02: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_1ba1f915f54c8d29d5766cc9b0efe0f2: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablee12f5b7476cba16c3b1480cd551d2b42 {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_2d1dc1e61d32d9314f690ef19eb8f9fd: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_1cbcac9ade6914a00f55838acea44222: Generated<number | null>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_806b0741c2f0a4352120014e6e8da433: Generated<number | null>\n  col_0e5abe8ffb47ede536aabfba66a14e05: Generated<number | null>\n  col_53a208b112254787b9ebe57338d2e92a: Generated<number | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablea6ca43be611a38117221fef4c761f97d {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_843fac686ca11587b97725cce2efc1d3: Date\n  col_2d1dc1e61d32d9314f690ef19eb8f9fd: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_1cbcac9ade6914a00f55838acea44222: number\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_59ec69fccca64cd638f1a7bf443b435c: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablef83eda9e66948a4da342fadf183e32c3 {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_983e58ca1a916d68762b2e241424e85c: number\n  id: Generated<number>\n  col_1ba1f915f54c8d29d5766cc9b0efe0f2: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tabledfc2f0e19fe1c0e8dd04191a3035bac8 {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_be69efe0e6bc75464cc24f246e61a62d: number\n  id: Generated<number>\n  col_1ba1f915f54c8d29d5766cc9b0efe0f2: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table93f030da0924f35ab2e57081dad1e2fb {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_22bd050ad65b2aa12639b75318b0864b: number\n  col_1ba1f915f54c8d29d5766cc9b0efe0f2: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table59fc5666d6be52faaeb255fb48a401ef {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_1ba1f915f54c8d29d5766cc9b0efe0f2: Generated<number>\n  col_fd21606544b271feae0784633a57d457: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table29c7f8f8df026c49d8ea3ad088e8780a {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_1ba1f915f54c8d29d5766cc9b0efe0f2: Generated<number>\n  col_a1625f77580ae88538a0bba96298b5ba: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table2e5e86f744edaeea91caedf4496cd21e {\n  col_8a79872b2fd9eca20ec1e0823abe36fa: Generated<string | null>\n  col_8ba45d6c9fbc6997e452dc62a60c32aa: Generated<string | null>\n  col_a538a4b49163b8abcdcff07958d6290c: Generated<number | null>\n  col_50d92f9a5774b1f89abbbc4ac7f546f0: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_62bd695be89e0f07c72268b40df9c2db: number\n  col_0a1609965fcbf80a8d9847074a93618c: Generated<string | null>\n  col_970dbef257f683fb01a38f38a4086cc5: Generated<string | null>\n  col_95a573b127ca2c23a2ed1dbc7d03d29e: Generated<string | null>\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  col_a67abae8eff833edb8b78a2ded44f0b3: Date\n  id: Generated<number>\n  col_a0102029c5185262158dcdb7c1ae4f51: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: Decimal\n  col_e85e859e6b11ce398d9c6ba4466648c2: Generated<string | null>\n  col_6fcadaf6349923a75d54632571ccec9d: Generated<string | null>\n  col_bd5c3d71904e9ae0f0e22b76c11590fd: Generated<string | null>\n  col_5b75dbfc85a5e0870a34cc3bfa2cf2ae: Generated<string | null>\n  col_910c87c70d93d69a64538ffc358a99de: string\n  col_ad3ab5438edd60f6c8638824072acd87: Generated<string | null>\n  col_b1146d17cb361aeddbb1108e39afbfd5: Generated<string | null>\n}\n\nexport interface Table27112b32955bc32b3cf3abc78f6041f7 {\n  col_f32428508672211d04f041977bc90510: string\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  col_2f6e73ed4e950f4879aa2dc43e832206: Generated<string | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_e245eb517472187d10441eca2c4a9aeb: number\n}\n\nexport interface Table6a8129f282adc469ee9233bcf63f20b7 {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_aeffdc77f4dde5fd265842bc848e92d1: number\n}\n\nexport interface Table55cda7b389c3f5e26b58e806dc82d6cd {\n  col_0f38d1a543b96eb8d34b6fcdc9227445: Generated<number>\n  col_aa0ae4d63455847b0b02a481f9f38ab7: number\n  col_05f720d878e84cf5edf8810ac56f2f47: Generated<string | null>\n  col_b599f327b0f1350c83e6466016f68dee: string\n  col_3c21e15fe7f88da04c6eb6546f1f0c45: string\n  col_55caff057cf8c83fe28641f2903d6bcd: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_e3c09cb3d68235ebdf5820c49f6ef2e0: Generated<string | null>\n  col_d48e0f172023094addf3ba3611199190: string\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_c613b7206854402371564704dbd689db: string\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_d69c485b8a1572710f1a3736bd1ac46c: Generated<'no' | 'si'>\n  col_032711695edadad1acb9974d043ec642: Generated<number>\n  col_ef1e84bf5d70755290854b1d0d60c91f: string\n  col_8b5da04bf1aacd462ab37eec2f0dea98: string\n}\n\nexport interface Tabledddb567693b67dedccc76feeaf305885 {\n  col_05f720d878e84cf5edf8810ac56f2f47: Generated<string | null>\n  col_b599f327b0f1350c83e6466016f68dee: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_e3c09cb3d68235ebdf5820c49f6ef2e0: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_c613b7206854402371564704dbd689db: string\n  col_cd241d70370d7d244f5103c80efc4b61: Generated<number | null>\n  id: Generated<number>\n  col_3e68cb4bb944a2eb1873d121e2c1da9f: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_d69c485b8a1572710f1a3736bd1ac46c: Generated<number>\n  col_3cc361b85f6e092837024f5ab2bdc2fe: Generated<number>\n  col_032711695edadad1acb9974d043ec642: Generated<number>\n  col_ef1e84bf5d70755290854b1d0d60c91f: Generated<string | null>\n  col_8b5da04bf1aacd462ab37eec2f0dea98: Generated<string | null>\n}\n\nexport interface Tableb45f137169628885a5507a98a1fd203b {\n  col_f32428508672211d04f041977bc90510: number\n  col_f77bbbe9a817f1a5818e71efaa20b892: string\n  id: Generated<number>\n}\n\nexport interface Table4d0fb43fef8f71d027e1c62ff7b83c1f {\n  col_f83b4cd2b2e7335a200c2da830132390: Date\n  id: Generated<number>\n  col_fde60bdc79a24d633ee18347600cb41d: string\n}\n\nexport interface Table26d9e67842818bfccbbfca6020d3441a {\n  col_f32428508672211d04f041977bc90510: number\n  col_f77bbbe9a817f1a5818e71efaa20b892: string\n  id: Generated<number>\n}\n\nexport interface Tablee6de3a3fdf132b2b794ad9358fe01719 {\n  col_748f83ef971bb7d351a413adbf1e8901: number\n  id: Generated<number>\n  col_7bc8772e9a79ea91b67b0fe68827dd3b: number\n  col_428661c5270745369a9118d95829ff49: Generated<Date | null>\n  col_b200a854685602c04809e2fad82ee47b: Generated<number | null>\n  col_54b8d01ca49e18a004dd65e012f28c4d: Generated<string | null>\n}\n\nexport interface Table5bdeb7407d8776f9295b3ae2eb482855 {\n  col_f32428508672211d04f041977bc90510: number\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: Generated<string | null>\n}\n\nexport interface Table259a82d9d67d1b779666191753027e2d {\n  col_b606d1948094a48e695e46b18cf977b1: Generated<number>\n  col_4f1b7b2483b9bb0a8b355ef69f09d65e: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_672a81e3795c2fd45450d85e0d3703e1: Generated<number | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tabledfcfa50cfe70d46b898ed0fe276855e4 {\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  id: Generated<number>\n}\n\nexport interface Table11e00101e1b2f60d0a2acfcf46151908 {\n  col_f4dffeda79e0ee34f16d57241b615f53: Generated<number | null>\n  col_b738ecc416fa96f41459da0404cdbf50: Generated<string | null>\n  col_25cd93f430d277509b60d4390636895f: string\n  col_44381c5d8d2d9361dd21bb7a7facf4b0: Generated<number | null>\n  col_0259f6499a0cb3f370a6119054eea3f3: Generated<number | null>\n  col_b6fec9e01d482caca6ab785b9c508583: Generated<string | null>\n  col_fe3144cfd0702470a18811a50b2a773a: Generated<string | null>\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_4a2d849a39589cdab1bef664bbaf662f: Generated<number | null>\n  col_5306bd08c84506786847c551137592aa: Generated<number | null>\n  col_f901883e4b25324963cbb061fed4eaec: Generated<string | null>\n  col_bb8f173dd39e2bbd2ca8bb502bdd5d7e: number\n  col_645e3472df388d4789ad6a12715cc7a9: Generated<number | null>\n  col_eade66be3d5c19459dbb52d65e58a9ff: Generated<string | null>\n  col_78f5ba4e82866b7d30d1c63b058b5042: Generated<string | null>\n  col_ed68df9dcbc6be1e74aa52f2aaac27b3: Generated<string | null>\n  col_9b0c62311c53c898ce6699696d685a14: Generated<number | null>\n  col_a19773e01d56a8727f9b50bfd98b67a7: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_95a573b127ca2c23a2ed1dbc7d03d29e: Generated<\n    'aceptado' | 'rechazado' | 'recibido' | null\n  >\n  col_7e208df123f1106ac3cf9c9ce582df87: Generated<number | null>\n  col_78729121eb966294e69d86f8b656c99d: Generated<string | null>\n  col_cac71ab1db07fe38f5915b92b9959348: Generated<string | null>\n  col_6310539ac8c0b13a896e8b9634e1e0c8: Generated<number | null>\n  col_8d66d088a1a8bcfb6a7477360f1a03e4: Generated<Date | null>\n  col_8f4a31364a65a9f539032a16e3f4ea8b: Date\n  col_bbeb11288ba33af45a8a7251cb87da2c: Generated<Date | null>\n  col_e199cc093d54f6c562ad8d547976c5df: Generated<Date | null>\n  col_e26de993b80283e73a98d2f5a7655e44: Generated<Date | null>\n  col_7a9cd04d755a1c1f269ce7184b943521: Generated<Date | null>\n  col_7426b7174c1b7d22061329a60b94e63f: number\n  col_1cc17f0951cd6972739a3cf858f985e2: Generated<number | null>\n  col_0364c29fe7237f4f6ffba597544b4f46: Generated<number | null>\n  id: Generated<number>\n  col_2499572f76367bcbe5ea0e76d6a53cfa: Generated<number | null>\n  col_3f38469c48f069fcc4f623bca8c587f6: Generated<string | null>\n  col_d6ffe41368d46575efb6f237e05643f8: Generated<number | null>\n  col_387852799fd39a75bb0ffbb3a088106e: Generated<number | null>\n  col_ea14b84c81e7ebecb1faf4ce83b8826b: number\n  col_9a4570bd056ea2d9dd0a6dbb83206443: Generated<number | null>\n  col_4002e95484dd522e663c6fac8757d914: Generated<number | null>\n  col_01b47914fe373f6ade80d5d3afef6847: Generated<number | null>\n  col_a3c438c6f272e35cd2f6e1a4f59dec67: Generated<number | null>\n  col_ef8a0d1ea2ae246640e55a5f585324f4: Generated<number | null>\n  col_256cd843e152753550cd6aa845f56fd8: Generated<number | null>\n  col_6360ba5916d4e8415f464336177c02e7: Generated<number | null>\n  col_5410929b23ebb3020d600feea427cdb7: Generated<number | null>\n  col_2924351c3f723a33dfd4dc659a06be9c: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_83ca342b1dd50c4c7999010b9ad6683a: Generated<string | null>\n  col_43c33f96a8b44d501f45cd6b9382f9df: Generated<string | null>\n  col_7b4b1dd4aafa937e34cb562a048e4fbb: Generated<number | null>\n  col_0191c0aa0d39de591b5236b304496123: number\n  col_2baa55cecfe99708f15031b74cdd7d36: Generated<number | null>\n  col_9e2f281c14fe1c305bf0613edb1b5467: Generated<string | null>\n  col_cb9ad148d424c04f44d3959334b394d9: Generated<number | null>\n  col_9bba3bbc7094c759a61d84f8605ba3b7: Generated<number | null>\n  col_5c63e943a6e825630ccaefcbed7a719b: number\n  col_41e744edec4d69e40ddd093f4e1b84aa: Generated<number | null>\n  col_83750383555947e4ccbd9661a0948ffe: number\n  col_02f2a2f220f28476f9c5ae7f0edfc060: Generated<string | null>\n  col_6052d6d42f76bc5ee164f458689e7274: Generated<string | null>\n  col_1044fcff754bb0008ba077f4fdc005f4: Generated<number | null>\n  col_bcbc405c655f95f2343eb1fb3288a05b: Generated<number | null>\n  col_aeffdc77f4dde5fd265842bc848e92d1: number\n  col_870d427af1d948c352eea11ffd952d1d: number\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n  col_ef1e84bf5d70755290854b1d0d60c91f: string\n  col_8ccb00b1ec3203ead93c89b315af7cfa: string\n  col_f8b0d195967998d8afabe1b39912ae34: string\n  col_0db72b58ea6b0b1a2468f44c3a154621: Generated<number | null>\n  col_75afa9f93f59b9a0da5fc050cf61454d: Generated<number | null>\n  col_3b24e1adfd3713e88eb334dd342f072b: Generated<number | null>\n  col_8c36708787079d53e4bb54ddc6d4cc93: Generated<string | null>\n  col_910c87c70d93d69a64538ffc358a99de: number\n  col_99b14a294256f4d99bff89feb7483caf: Generated<string | null>\n  col_6dbc88c5b052629e050a099e04d7be3f: Generated<number | null>\n  col_f1f2f079861a9877106a6209fe34974d: Generated<string | null>\n  col_b96e29426fd3636dd5bc9ce5b03a13df: Generated<string | null>\n  col_416bce439c6a2ac5ac9dbd1b0947e48a: Generated<Date | null>\n  col_079842fe7e15f5de8a65e411c9df3787: Generated<string | null>\n  col_0aff87eb8d3d48fa89e873060f0715d4: Generated<string | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n  col_2923af0fb0193af631f34d210c0247df: Generated<number | null>\n}\n\nexport interface Tableaa828347830464c8d6fb6070585f8786 {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_bbe02f946d5455d74616fc9777557c22: string\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n}\n\nexport interface Table5e1a250360f2e59810faaec5dec74bfb {\n  col_4f1b7b2483b9bb0a8b355ef69f09d65e: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<Date | null>\n  col_7db3960deab1cd20d8b5b1f5501f3987: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablecb67af6a70220cf4b2c4e1121d9351c6 {\n  col_c2794c3a6a63d8743b9aa8499f407b15: string\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table01687ac6f71bbab86d7fb8482bf71301 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_80ae6f72f9c170f9e1bcae48c1677802: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: Generated<string | null>\n  col_16f39dcb91dd929ebf8bea9f30568523: number\n  col_0e759e13c162a5f46e9c6ad11ff37c68: number\n}\n\nexport interface Tablee4612831426584576f2d39997ccac9c8 {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: Generated<number | null>\n  id: Generated<number>\n  col_84267f80102ea16f25ffe6f5be92255e: Generated<number | null>\n  col_c55b5208e65984aac86ada39165d9d62: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n}\n\nexport interface Tablebca1b3f3c2526216b2f01c01fa85f3f9 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_47800dcca216b1b165c13199d66c3b63: Generated<number | null>\n  id: Generated<number>\n  col_c55b5208e65984aac86ada39165d9d62: Generated<number | null>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n}\n\nexport interface Tablecac2eaeb16e94e019e7e98240c4bac17 {\n  col_3886a084aa5ac96babd5443af176b2fa: Generated<number | null>\n  col_e91148e8d587cad1668a1e01d4701bd4: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_756c412732c9e787f483d35d939b8ef2: Generated<string | null>\n}\n\nexport interface Table7eb5460a0c6690c1dff53fe4940240db {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: string\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table5c88bed5704d2054a84d44150bf10f21 {\n  col_f60a220f6974819d5fb5760aed1c4cd0: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_756c412732c9e787f483d35d939b8ef2: string\n}\n\nexport interface Table148eb9256ed9e01df75e345bd7e5c9f7 {\n  col_d109701b76ff710c8e7fddd648466bac: string\n  col_066a120fe3abe924fdd105d2073b3a64: Generated<number | null>\n  col_08114ce1193bf6826c3277f27236a6d8: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_4f84013a8b5e4c2b7529058c8fafcaa8: string\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_3917508388f24a50271f7088b657123c: Generated<string | null>\n}\n\nexport interface Tablee2c77a8b952bdea3bc2cb7261168ec45 {\n  col_c06fbc27fba97ced26a9d976caa41a75: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_a94fa2fac7c75e7343d9de23fa2ee836: number\n}\n\nexport interface Tableabd2380e09dc7a608bb7e5c33654540e {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_2cf1ecc054fac526249f379db15f6114: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_f136803ab9c241079ba0cc1b5d02ee77: string\n}\n\nexport interface Table7117bf3bff290101f4fa6d6de627b58f {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_8b5da04bf1aacd462ab37eec2f0dea98: Generated<string | null>\n  col_f136803ab9c241079ba0cc1b5d02ee77: string\n  col_20be803fa76256ebff5a3090a351dce6: string\n}\n\nexport interface Table202a1f7684d2c58afd3885112de82158 {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_f136803ab9c241079ba0cc1b5d02ee77: string\n}\n\nexport interface Table93aeee94c0d8d4e08a56c97185d68ae7 {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_f136803ab9c241079ba0cc1b5d02ee77: string\n}\n\nexport interface Table70c085cf2d0edd14f7dbae474f064b1c {\n  col_495188e3a36574928230c0e978a9c24b: string\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n}\n\nexport interface Table2b11443e8af088b453d5119d135803ac {\n  col_c380dabd328dc1bc21400bb6319fe82e: Generated<number | null>\n  col_46df0ccd51bb26538db287f8e4e6e4dd: Generated<number | null>\n  col_f32428508672211d04f041977bc90510: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_6f2528e6259a627108655e46967927b1: Generated<number | null>\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number | null>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: Generated<string | null>\n  col_40cee1e4d1c6b882095d5d343de8a0e2: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_aeffdc77f4dde5fd265842bc848e92d1: Generated<number | null>\n  col_de936835b986b7e9a72b8706204dc183: Generated<number>\n  col_105b287b6f42e3e08bccae5fa0bc1e57: Generated<number | null>\n  col_4bf016b629fc04e08a3080d945fff2e3: Generated<number | null>\n  col_10c0a78ec67f5765bb129e53d403a805: Generated<number | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table0a542ca892cb0eea27538d7360f718ec {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: Generated<number | null>\n  col_76b9a01c6151dd633f8055cde973a800: Generated<number | null>\n  col_1d9d9279776c5549212200cb14336162: string\n  col_e78e90b28ac15ec4ffca85e98e8c9ba3: Generated<Date | null>\n  col_13715b2fa41756ef623ff3afe3ad7061: Generated<number | null>\n  col_3886a084aa5ac96babd5443af176b2fa: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_ed9b82a66d24b12f15e6c804b8e2987a: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_1f6eddf77651742ff1d83404930b09ae: string\n  col_18f2a0599c2957ceab7b1d9810c178af: Generated<number>\n  col_c5afa3714e1eb36f2ef051adb19d53a1: string\n  col_50169df6c46157b06e457a2215bafaa3: string\n  col_22b038c1818e66252d7965200369f7b8: string\n}\n\nexport interface Tableb8378493b92a26626ae5745222c8ba69 {\n  col_535325947cf44473a2c18fad07fe9457: number\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  col_62bd695be89e0f07c72268b40df9c2db: number\n  col_34e7aea5cf0f74ee76b3f5445a3ac1cf: Date\n  col_c84d2025f9e13529cf7b4aa05275bdf6: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date>\n  col_2700d8a25d8d8e80c4ad5b622ea5dbec: number\n  col_3d1ca4769fb6a0b43de8fd6c85704dde: number\n}\n\nexport interface Table565a308ecf3782bb5eb0197187361913 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_e78e7faf2c91332782285f057698f37f: string\n}\n\nexport interface Tablede86128413dcd68bd6d1ca009b6bae17 {\n  col_821c248ea5f31b36e1fef43cbcf38495: Generated<string | null>\n  col_49a7abbdc564bf92a27c31a936047cda: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n}\n\nexport interface Table57dadc25e9a34c53f66b5cb499d75904 {\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: string\n  col_d141deef0d42e47261b99f7b286068d8: Generated<number | null>\n  col_f35d7efe3efb3e67af82d59c734bf437: string\n}\n\nexport interface Table366c7f7bccaea5ff455a9b9265448ebf {\n  col_535325947cf44473a2c18fad07fe9457: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_2598a0c1aa229293b50e76e77b92ab0e: Generated<number | null>\n  col_8f4a31364a65a9f539032a16e3f4ea8b: Generated<Date | null>\n  col_7a9cd04d755a1c1f269ce7184b943521: Generated<Date | null>\n  col_6ea44f04ea696f044e04871607c145ab: Generated<string | null>\n  col_7426b7174c1b7d22061329a60b94e63f: Generated<string | null>\n  col_33cee772b203aed80ee06d3dcb2cbcd0: Generated<number | null>\n  id: Generated<number>\n  col_3e68cb4bb944a2eb1873d121e2c1da9f: Generated<string | null>\n  col_b114935b452a2d927bd5ac81ad9a3d67: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: number\n  col_e66275f52358e1042acff2dc629ecf3d: number\n  col_888ef26444026e2cf7e456521447a5cf: number\n  col_0169d667d30453fc6d348ede68c6137e: number\n  col_0191c0aa0d39de591b5236b304496123: number\n  col_ea32f0629d5780f0b84ac3c2dc29354c: number\n  col_83750383555947e4ccbd9661a0948ffe: number\n  col_ef1e84bf5d70755290854b1d0d60c91f: Generated<string | null>\n  col_53a208b112254787b9ebe57338d2e92a: Generated<Decimal>\n  col_0511961bf51aa24c76ca49e18e4395e9: Generated<number | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: Generated<number | null>\n}\n\nexport interface Tablea4ca5018c98bd7912524f97ccd0a8757 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  col_e7e1b5558e643c883f256414a76e28f7: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_aeffdc77f4dde5fd265842bc848e92d1: number\n}\n\nexport interface Table402dd89f94d2a88ccdf049224dfc8700 {\n  col_535325947cf44473a2c18fad07fe9457: Generated<number | null>\n  col_066a120fe3abe924fdd105d2073b3a64: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_2598a0c1aa229293b50e76e77b92ab0e: Generated<number | null>\n  col_8f4a31364a65a9f539032a16e3f4ea8b: Generated<Date | null>\n  col_7a9cd04d755a1c1f269ce7184b943521: Generated<Date | null>\n  col_6ea44f04ea696f044e04871607c145ab: Generated<string | null>\n  col_7426b7174c1b7d22061329a60b94e63f: Generated<string | null>\n  id: Generated<number>\n  col_3e68cb4bb944a2eb1873d121e2c1da9f: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: number\n  col_e66275f52358e1042acff2dc629ecf3d: number\n  col_888ef26444026e2cf7e456521447a5cf: number\n  col_0169d667d30453fc6d348ede68c6137e: number\n  col_0191c0aa0d39de591b5236b304496123: number\n  col_ea32f0629d5780f0b84ac3c2dc29354c: number\n  col_83750383555947e4ccbd9661a0948ffe: number\n  col_ef1e84bf5d70755290854b1d0d60c91f: Generated<string | null>\n  col_53a208b112254787b9ebe57338d2e92a: Generated<Decimal>\n  col_0511961bf51aa24c76ca49e18e4395e9: Generated<number | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: Generated<number | null>\n}\n\nexport interface Table92498a6babb7032cdcad6e43158a3359 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  col_e7e1b5558e643c883f256414a76e28f7: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_aeffdc77f4dde5fd265842bc848e92d1: number\n}\n\nexport interface Tablee90356817b37536144c4cf962e9e5165 {\n  col_b44e675732d485b4ded87fd63200ab77: number\n  col_21e3dbb834dd41bd22e04928fef6a335: number\n  id: Generated<number>\n  col_756c412732c9e787f483d35d939b8ef2: string\n}\n\nexport interface Table61a79fc440f7ca2d4190d47ee809f66c {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_7364a488f431ca7296b76a34417395b4: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_2598a0c1aa229293b50e76e77b92ab0e: Generated<number | null>\n  col_8f4a31364a65a9f539032a16e3f4ea8b: Generated<Date | null>\n  col_1690e4ca8c11ef9d61ca7213686d5c40: Generated<Date | null>\n  col_6ea44f04ea696f044e04871607c145ab: Generated<string | null>\n  col_7426b7174c1b7d22061329a60b94e63f: Generated<string | null>\n  col_d3dfe95339547ab875d57cd71ab15f81: Generated<number | null>\n  id: Generated<number>\n  col_3e68cb4bb944a2eb1873d121e2c1da9f: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: number\n  col_e66275f52358e1042acff2dc629ecf3d: number\n  col_888ef26444026e2cf7e456521447a5cf: number\n  col_0169d667d30453fc6d348ede68c6137e: number\n  col_835294398c028add3afb4e1cb897a4de: number\n  col_0191c0aa0d39de591b5236b304496123: number\n  col_ea32f0629d5780f0b84ac3c2dc29354c: number\n  col_83750383555947e4ccbd9661a0948ffe: number\n  col_ef1e84bf5d70755290854b1d0d60c91f: Generated<string | null>\n  col_8b9c30bb3038e2306d0186e3b78f5f3a: Generated<string | null>\n  col_53a208b112254787b9ebe57338d2e92a: Generated<Decimal>\n  col_0511961bf51aa24c76ca49e18e4395e9: Generated<number | null>\n  col_0d15b3ba535af3fa98a18834ca71c71f: Generated<number | null>\n  col_079842fe7e15f5de8a65e411c9df3787: Generated<string | null>\n  col_0aff87eb8d3d48fa89e873060f0715d4: Generated<string | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: Generated<number | null>\n}\n\nexport interface Table7051320fedfb456818eb15cdf217186d {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  col_e7e1b5558e643c883f256414a76e28f7: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_aeffdc77f4dde5fd265842bc848e92d1: number\n}\n\nexport interface Table2d7cdf1ccac4544f81ac78a12d5fba7a {\n  col_caaf808b80e56775d03b800fc5edf429: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  id: Generated<number>\n  col_369ce420bd39cdc51bfcfd33d861ba59: number\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_b1dc1e3377a082304d817664243e7b17: Decimal\n}\n\nexport interface Tablea8e3bfebcd001eac1185867f7dec94a5 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_910c87c70d93d69a64538ffc358a99de: Generated<string | null>\n}\n\nexport interface Table148ce21c70970d2809c4028c229445be {\n  col_f4dffeda79e0ee34f16d57241b615f53: Generated<number>\n  col_b738ecc416fa96f41459da0404cdbf50: Generated<string | null>\n  col_44381c5d8d2d9361dd21bb7a7facf4b0: Generated<number | null>\n  col_0259f6499a0cb3f370a6119054eea3f3: Generated<number | null>\n  col_08114ce1193bf6826c3277f27236a6d8: Generated<number | null>\n  col_fe3144cfd0702470a18811a50b2a773a: Generated<string | null>\n  col_8ce24ccf64416ee4c1737bf1ab0ea2f8: Generated<string | null>\n  col_4f1b7b2483b9bb0a8b355ef69f09d65e: string\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_4a2d849a39589cdab1bef664bbaf662f: Generated<number | null>\n  col_5306bd08c84506786847c551137592aa: Generated<number | null>\n  col_f901883e4b25324963cbb061fed4eaec: Generated<string | null>\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_bb8f173dd39e2bbd2ca8bb502bdd5d7e: number\n  col_645e3472df388d4789ad6a12715cc7a9: Generated<number | null>\n  col_eade66be3d5c19459dbb52d65e58a9ff: Generated<string | null>\n  col_78f5ba4e82866b7d30d1c63b058b5042: Generated<string | null>\n  col_ed68df9dcbc6be1e74aa52f2aaac27b3: Generated<string | null>\n  col_a222f017034f971d4a5004b53f0e9699: Generated<string | null>\n  col_9b0c62311c53c898ce6699696d685a14: Generated<number | null>\n  col_a19773e01d56a8727f9b50bfd98b67a7: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_0c7beee8ee787fec23562efa3adbf18a: number\n  col_2a5b75864f31fbe839a8f028ee554f53: Generated<number | null>\n  col_78729121eb966294e69d86f8b656c99d: Generated<string | null>\n  col_cac71ab1db07fe38f5915b92b9959348: Generated<string | null>\n  col_6310539ac8c0b13a896e8b9634e1e0c8: Generated<number | null>\n  col_1628a3796456964796ddec0bcb38d0e5: Generated<Date | null>\n  col_8f4a31364a65a9f539032a16e3f4ea8b: Date\n  col_d9d6c97f041fe7c54b65501f67fcfea9: Generated<Date | null>\n  col_bbeb11288ba33af45a8a7251cb87da2c: Generated<Date | null>\n  col_e199cc093d54f6c562ad8d547976c5df: Generated<Date | null>\n  col_e26de993b80283e73a98d2f5a7655e44: Generated<Date | null>\n  col_7a9cd04d755a1c1f269ce7184b943521: Generated<Date | null>\n  col_7426b7174c1b7d22061329a60b94e63f: number\n  col_1cc17f0951cd6972739a3cf858f985e2: Generated<number | null>\n  col_0364c29fe7237f4f6ffba597544b4f46: Generated<number | null>\n  id: Generated<number>\n  col_3f38469c48f069fcc4f623bca8c587f6: Generated<string | null>\n  col_d6ffe41368d46575efb6f237e05643f8: Generated<number | null>\n  col_478cb1787a1e2a0d75235f14a78b7929: Generated<number | null>\n  col_387852799fd39a75bb0ffbb3a088106e: Generated<number | null>\n  col_ea14b84c81e7ebecb1faf4ce83b8826b: number\n  col_4002e95484dd522e663c6fac8757d914: Generated<number | null>\n  col_01b47914fe373f6ade80d5d3afef6847: Generated<number | null>\n  col_a3c438c6f272e35cd2f6e1a4f59dec67: Generated<number | null>\n  col_ef8a0d1ea2ae246640e55a5f585324f4: Generated<number | null>\n  col_256cd843e152753550cd6aa845f56fd8: Generated<number | null>\n  col_6360ba5916d4e8415f464336177c02e7: Generated<number | null>\n  col_5410929b23ebb3020d600feea427cdb7: Generated<number | null>\n  col_2924351c3f723a33dfd4dc659a06be9c: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_83ca342b1dd50c4c7999010b9ad6683a: Generated<string | null>\n  col_43c33f96a8b44d501f45cd6b9382f9df: Generated<string | null>\n  col_7b4b1dd4aafa937e34cb562a048e4fbb: number\n  col_0191c0aa0d39de591b5236b304496123: number\n  col_3ad5d52faa1934f2661f8a9d39c48bcf: Generated<number | null>\n  col_2baa55cecfe99708f15031b74cdd7d36: Generated<number | null>\n  col_9e2f281c14fe1c305bf0613edb1b5467: Generated<string | null>\n  col_cb9ad148d424c04f44d3959334b394d9: Generated<string | null>\n  col_5c63e943a6e825630ccaefcbed7a719b: number\n  col_641b931cd172a7b80d81f8e994faed0f: Generated<number | null>\n  col_83750383555947e4ccbd9661a0948ffe: number\n  col_32fae7a6a5f2cd2d02cbdfac22bb3aee: Generated<number | null>\n  col_02f2a2f220f28476f9c5ae7f0edfc060: Generated<string | null>\n  col_6052d6d42f76bc5ee164f458689e7274: Generated<string | null>\n  col_1044fcff754bb0008ba077f4fdc005f4: Generated<number | null>\n  col_bcbc405c655f95f2343eb1fb3288a05b: Generated<number | null>\n  col_9e3a10e7f5449c1de35f219e8d4a0b43: Generated<number | null>\n  col_aeffdc77f4dde5fd265842bc848e92d1: number\n  col_870d427af1d948c352eea11ffd952d1d: number\n  col_ef1e84bf5d70755290854b1d0d60c91f: string\n  col_8ccb00b1ec3203ead93c89b315af7cfa: string\n  col_8b5da04bf1aacd462ab37eec2f0dea98: string\n  col_a0714fe92c4ddead9939c0f656a43ba8: Generated<string | null>\n  col_7d39847d54a6fc52735c6a250cfce5eb: Generated<string | null>\n  col_0db72b58ea6b0b1a2468f44c3a154621: Generated<number | null>\n  col_75afa9f93f59b9a0da5fc050cf61454d: Generated<number | null>\n  col_3b24e1adfd3713e88eb334dd342f072b: Generated<number | null>\n  col_8c36708787079d53e4bb54ddc6d4cc93: Generated<string | null>\n  col_910c87c70d93d69a64538ffc358a99de: number\n  col_53a208b112254787b9ebe57338d2e92a: Generated<number | null>\n  col_4ab5b1dd04a8cefd62107890b80103cd: Generated<string | null>\n  col_6dbc88c5b052629e050a099e04d7be3f: Generated<number | null>\n  col_f1f2f079861a9877106a6209fe34974d: Generated<string | null>\n  col_972aaa3fbd7b8c3cb772ed1eb78becbb: Generated<string | null>\n  col_fb70e10e97efd8bc28a6c9cb1e9f9ff8: Generated<string | null>\n  col_b96e29426fd3636dd5bc9ce5b03a13df: Generated<string | null>\n  col_5f544d6483d4ce30cf3145abb40f9441: Generated<number | null>\n  col_bab5d43498aec1209e8ab958b766cb86: Generated<number | null>\n  col_416bce439c6a2ac5ac9dbd1b0947e48a: Generated<Date | null>\n  col_079842fe7e15f5de8a65e411c9df3787: Generated<string | null>\n  col_0aff87eb8d3d48fa89e873060f0715d4: Generated<string | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n  col_1e36674b6a9b366e7ac7dc0343291399: 'auto' | 'validado'\n  col_e7f37cd2de5c3de049e6ef13e7027769: 'auto' | 'validado'\n  col_2923af0fb0193af631f34d210c0247df: Generated<number | null>\n  col_df82ddd36c8d6387edc8c1d15e9e6e8d: Generated<string | null>\n  col_f990fa06e3da84de9a61af49e4b7957f: Generated<string | null>\n}\n\nexport interface Tablef650c769203b8bd7eed5a8b7e249c0a5 {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_7db3960deab1cd20d8b5b1f5501f3987: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_1ba1f915f54c8d29d5766cc9b0efe0f2: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table8b9070a970ee019dd472ce6c4a08418b {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_3924f75e4f7e65a64d2f06bad0a8da28: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tabled580c05f239408ff0392e235078a0ac9 {\n  col_a4513edcdb71f8647001257ec32ab4e1: string\n  col_2404b63b8a201d13a8735e0fa9b53478: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_1df5ee28c9955544f2ebe06a6c829b57: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_18697449d7c48cf32cdd4f14857e68ee: string\n  col_8368a8c92f592e349b57fc53fe6f98f4: Generated<string | null>\n  col_f57dbda547fc6e900a0f8a585ddd9b49: string\n  col_910c87c70d93d69a64538ffc358a99de: Generated<string | null>\n  col_a94fa2fac7c75e7343d9de23fa2ee836: number\n}\n\nexport interface Tabledd7d780df70068dcb36a8d8b86bd5298 {\n  col_a4c065a7262f640f0ac2b61885f9671c: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_b4226c098cbf79023e9a779b83ccd3c9: string\n  col_8a6902c3de19dedef52742ed22cff3ca: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_6177dfccf6065b1ec558e457a24dea33: string\n  col_aeffdc77f4dde5fd265842bc848e92d1: number\n  col_b1bac0f8e81aa2bc396eb0eacaf93f7d: string\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table48df920caa8cc60fd47820e9d94ea940 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  id: Generated<number>\n  col_216979ad27e40ff49f5d477cb3ebad3c: string\n  col_1430120f960285493d5121f4e9f1d924: string\n}\n\nexport interface Table9bb0301f7ca02953fac2add8dcd7630c {\n  col_1d726898491fbca9a8dac855d2be1be8: Generated<number | null>\n  col_d109701b76ff710c8e7fddd648466bac: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_4f84013a8b5e4c2b7529058c8fafcaa8: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_3e68cb4bb944a2eb1873d121e2c1da9f: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_8b5da04bf1aacd462ab37eec2f0dea98: Generated<string | null>\n}\n\nexport interface Table5492e76278a71210d7231f4bf905ec2f {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: Generated<number>\n  col_fa769b4ad2c48f942621b456579a2224: Generated<string | null>\n  col_0e26753c5fe14eae84568b5a83e79ded: Generated<number>\n  col_08b4d026d42ae768f63552c6de119d71: Generated<string | null>\n  col_60f7d4dabf428b3a6d7d624e3e8f92ef: Generated<string>\n  col_05f720d878e84cf5edf8810ac56f2f47: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_e3c09cb3d68235ebdf5820c49f6ef2e0: Generated<string | null>\n  col_e8597efec888f22158cf26c4a354b45e: Generated<number>\n  col_c68408fb5945c7ed27cfe1fb9ac4c2ea: Generated<'afecta' | 'exenta'>\n  col_151fd0d998f5df50fcc7d39143f704be:\n    | 'acepta'\n    | 'agilice'\n    | 'bsale'\n    | 'iconstruye'\n    | 'mipyme'\n    | 'nubox'\n    | 'otro'\n    | 'simpledte'\n  col_99a8177c44470ec20b0097b78d30d2ab: number\n  col_99f35f96dabaa98303aaa135bfdc0404: Date\n  col_a4ce5705c5f18b69e4add952a187bdde: Date\n  col_c613b7206854402371564704dbd689db: Generated<string | null>\n  col_355ea60efdcf57aa297299ab210b4e7d: Generated<number>\n  col_b2272775d9787c60c9479000c8b8088a: Generated<string | null>\n  id: Generated<number>\n  col_3e68cb4bb944a2eb1873d121e2c1da9f: Generated<string | null>\n  col_a766059eaf3814aa9e73448453e9270c: Generated<number | null>\n  col_aba4dc94d2f01540b5dbb57d1096c59b: Date\n  col_7dab8a0fad43f3c1c0c352252aac807f: Generated<number | null>\n  col_98d8d6a239ae64c6f2fc402b7a7847d8: Generated<string | null>\n  col_9f7b242c1ab922eb24d0a3ae403e9676: Generated<string | null>\n  col_d5a21723ffc4d83c5ab428a5878324b9: string\n  col_15deb4ee2f0424b3885142c477ba88b9: string\n  col_042f170682938c181254695986457b1b: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number | null>\n  col_f639c93a74ec468c5609505b10e90eea: Generated<number>\n  col_ba39ea3526b3c7a1ab364b9298d40d78: Generated<number | null>\n  col_ad014db14bea88133e71209061b6bd74: Generated<number | null>\n  col_90e4c91b2d55ab42c9930ec06e506ee4: Generated<number>\n  col_d420d89b7ce762fa312a4437bccb99c6: number\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_e245eb517472187d10441eca2c4a9aeb: Generated<number>\n  col_651324890c5c5b8c2193ad39bfa36c05: string\n  col_164b7896ec8e770207febe0812c5f052: Generated<number>\n  col_40772ba813d97356c66a42e44c29f2f2: Generated<number | null>\n  col_4e893eedef52baaf8f70770064c00f91: Generated<number>\n  col_1d958835f7ab52daf74459d71c0c66d1: Generated<number>\n  col_ef1e84bf5d70755290854b1d0d60c91f: string\n  col_91d2a3cd2d79ad40574b4c2ec58584c1: Generated<string | null>\n  col_e85a2e013135b7b178241e6fc32327a8: Generated<number | null>\n  col_8b5da04bf1aacd462ab37eec2f0dea98: string\n  col_cb72fdda441d8ab0ee9b88e25961fd83: Generated<number>\n  col_f9dd44edd9eab46a126cfec00a028907: Generated<Date | null>\n  col_7c2b7d5981088f354990946bb421e222: string\n  col_70b0729c3bbf27533b98759ae98fb40e: Generated<string | null>\n}\n\nexport interface Tableea8e45026529937b0cecd544d8801cfd {\n  col_bdaef2864913fee6a3be8029d46830a6: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_2414ddf934cafab5eb8e6fbe3478710e: string\n}\n\nexport interface Table574ff9acd571619424cd55716f5f1dfb {\n  col_95a573b127ca2c23a2ed1dbc7d03d29e: string\n  id: Generated<number>\n}\n\nexport interface Tablea79aeca54482635868f02356a51fa369 {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tablee7a44a84d410fa64377504e3aa7f72b6 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_99a8177c44470ec20b0097b78d30d2ab: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tabledcc9250fc52d5fbc25a56cf9c4089073 {\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_95a573b127ca2c23a2ed1dbc7d03d29e: Generated<string | null>\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: string\n}\n\nexport interface Table4d82bf6c52ed1355768c73593994c5c2 {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: Generated<string | null>\n}\n\nexport interface Table73f359bc2658d254af39135aed8c3bf2 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_4377992db876783f2aced4af1b7cc195: number\n}\n\nexport interface Table8cf85c63dc3200ef8145fc0344d00f16 {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: Generated<string | null>\n}\n\nexport interface Table401ef7ed8ddaa97932ede0de0b157c04 {\n  col_95a573b127ca2c23a2ed1dbc7d03d29e: string\n  id: Generated<number>\n}\n\nexport interface Table3e875ede7feab48a89082e0c87c364f0 {\n  col_d08c3aaad1d4c926a4bf283098fcc325: string\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_d141deef0d42e47261b99f7b286068d8: Generated<number | null>\n}\n\nexport interface Table7822bcc86140bf34bc6cdacbd734c0ef {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_a15701e29e0d577f5252d616c1f13273: number\n  col_e6c19fe14ec531d7b295d1723a4b8e03: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_72f96160fd66ba04a6c4d17116faca2a: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_6eabf912118c656e74717bf86ec69f73: number\n  col_b2211a70f2ff7369336027ed47f18f7f: Generated<number | null>\n  col_923c1ce4be0acf2cf56890bbd41ec804: Generated<string>\n}\n\nexport interface Table459dc31349051f20a755552adaf60c81 {\n  col_460c9eed028ead37612e14da1dd10330: number\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_6c5493e52a59d7de52511ba52276ddcd: Generated<number | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_112f837ef3cfed0e17742e284a1769e7: Generated<number | null>\n}\n\nexport interface Table1b8610f190607dfbdafa9c71f72acd43 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_fb697b0790ebaa204d9bffad490998af: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n}\n\nexport interface Table1edc1b921ba66176c3ec62961c248f78 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table9b72afad4afd63d81ab6ef56c926765d {\n  col_fc00b65a31d011aa9c5cac6511de984e: Generated<number>\n  col_4f1b7b2483b9bb0a8b355ef69f09d65e: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: string\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n  col_756c412732c9e787f483d35d939b8ef2: Generated<number>\n}\n\nexport interface Table309e0b9a80a4ad911a672f7174429e35 {\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  id: Generated<number>\n}\n\nexport interface Tablea0eb46b195e5cbd5e85384a9a1622c14 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_eeec804da0fd1aeeb188a033dc67b8a2: Generated<string | null>\n  col_a2485bfd6e0a49a04be5fbb9ed0123e9: Generated<string | null>\n  col_76ef16690bb4ed0aba9768175f242b63: Generated<string | null>\n  col_1e23790fd5accaa0afa87349f9791709: Generated<string | null>\n  col_f0d54e8da1328799154329bc93eb4b55: string\n  col_f1f2f079861a9877106a6209fe34974d: Generated<string | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tableea5b8f9c56ff4ae4cb3c8f22541b33ba {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: number\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_1f7ca930a1d20b8732208df17a3f204a: Generated<number | null>\n  col_74acc07e501e952b631264318b0a5ba9: Generated<number>\n  id: Generated<number>\n  col_c55b5208e65984aac86ada39165d9d62: Generated<number | null>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: Generated<string>\n  col_df15c6be5f4fc31ef5a0a4fe0ae82481: Generated<string | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_aeffdc77f4dde5fd265842bc848e92d1: Generated<number | null>\n  col_aff776838092862d398b58e380901753: Generated<number>\n}\n\nexport interface Table3a87f98012aa2362e8eb64ed4d9e8f65 {\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: string\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_0ba81706c32fe49f7691637abff566ac: Generated<number>\n}\n\nexport interface Tablefe2e32091534caf00911fc7435cbc97b {\n  col_6a59e77ab0765a9b1e48a245087e5bbd: number\n  col_512820308ce62e853b7c389614ef5adb: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_57785655fe648f6c416a0d3024567b5e: number\n  id: Generated<number>\n  col_805df4d52c1afca7f1fe90a63e932648: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_3326c052986bfda9670541e3279e2a4d: Generated<number>\n}\n\nexport interface Table3cdcee0d77b622e8a2ec654a21270877 {\n  col_57785655fe648f6c416a0d3024567b5e: number\n  id: Generated<number>\n  col_169ab89ce8908eabce9ec3b6c5350b3a: Generated<number>\n  col_e82af1a7ad08756ecd516aef27dd0510: number\n  col_e245eb517472187d10441eca2c4a9aeb: number\n  col_e7fa32cb05ba9ddc8d5f75bdf1694790: Generated<string | null>\n  col_ed735d6320ed39d39ecf94e63bcbbe78: Generated<string | null>\n}\n\nexport interface Table8077f242ad5e05394a3dd81ce79565f7 {\n  col_90412006b8822d49b8306f1cebb4b244: Generated<number | null>\n  col_57785655fe648f6c416a0d3024567b5e: number\n  id: Generated<number>\n  col_3326c052986bfda9670541e3279e2a4d: Generated<number>\n  col_40772ba813d97356c66a42e44c29f2f2: number\n}\n\nexport interface Table52a8644bfd17799495525f2fd8adc480 {\n  col_25cd93f430d277509b60d4390636895f: Generated<string | null>\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number | null>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_c8cdc4633fd519ba66ab3e84fdb9e5b3: Generated<string | null>\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n  col_eeec804da0fd1aeeb188a033dc67b8a2: string\n  col_a2485bfd6e0a49a04be5fbb9ed0123e9: Generated<string | null>\n  col_53a208b112254787b9ebe57338d2e92a: Generated<Decimal>\n  col_0ba2161c945373e22c9989c68a51937c: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: Generated<number | null>\n}\n\nexport interface Table74bb684c41a71a06f561e10ffa4e3323 {\n  col_fc64eb6054f462d6d323dd7c2e2ff768: Decimal\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_f609bfdeed2c51dbb142fd03bddfd02a: Generated<number | null>\n  col_5c63e943a6e825630ccaefcbed7a719b: Generated<number | null>\n  col_83750383555947e4ccbd9661a0948ffe: Generated<number | null>\n  col_b2211a70f2ff7369336027ed47f18f7f: Generated<number | null>\n  col_6092393019ca918cd006522bd308d5e8: number\n}\n\nexport interface Table64ac7b9a171e9af222924b693d44887c {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablefd230cdd0c0d7bc04b06cffa3bc3fa3e {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_9f4a15cb3f14b10397b11f224b181199: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_aff776838092862d398b58e380901753: Generated<number>\n}\n\nexport interface Table2bf8003c7e2a7344f4d30c3a351926c5 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table5c1f23359d009924d75dac9200da99ab {\n  col_fee6d937834161cc73b3698fee871f5c: string\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_9b0c62311c53c898ce6699696d685a14: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_95a573b127ca2c23a2ed1dbc7d03d29e: string\n  col_8f4a31364a65a9f539032a16e3f4ea8b: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_25980343ed3b4c231a154e5e88396938: number\n  col_fb1ecce130681efa10fd55197773267d: number\n  col_d8ad55006c0efc8437cc487b5c5459f6: number\n  col_01abc2f9e295923216e8462e3a88bf5d: string\n  col_ea7e482493b72c75cf90057ba252352b: number\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n  col_f8b0d195967998d8afabe1b39912ae34: string\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablea6cdaf7c2c1c27d8389fb8ec7831b240 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_c69fd88c6f0d5f2db866eaf69baa2554: string\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: Generated<number | null>\n  col_00b4288b12a81b04c5f2479addcec521: Generated<number>\n}\n\nexport interface Table618b14672aa41a4ddbaa07b4668e9ceb {\n  col_066a120fe3abe924fdd105d2073b3a64: number\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  col_7364a488f431ca7296b76a34417395b4: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_e842d3a41f6119b9ea97d9966c87fe4a: number\n  id: Generated<number>\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n  col_b2211a70f2ff7369336027ed47f18f7f: number\n}\n\nexport interface Tablee0ac1a12db533e45722bf75854c5f68f {\n  col_25cd93f430d277509b60d4390636895f: string\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_9b0c62311c53c898ce6699696d685a14: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n  col_910c87c70d93d69a64538ffc358a99de: Generated<\n    'F20' | 'F22' | 'F29' | 'F30' | 'F50'\n  >\n  col_91b6293c3ca6646fe348ce8a4f4b4c85: Generated<number | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table6b64130a9ac5e9179051a15684e76956 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_0f8a9471827ba9a9ddd4ce0e2ddd1a00: number\n  id: Generated<number>\n  col_22bd050ad65b2aa12639b75318b0864b: number\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n}\n\nexport interface Tablec3c4b9ba46ff23ee52e9fa59ba4cbd42 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_38a15d7f839694e0cbb6b3feacd63ea8: number\n  id: Generated<number>\n  col_22bd050ad65b2aa12639b75318b0864b: number\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n}\n\nexport interface Tableac8f964f7407177bed83d5a1b563c4be {\n  id: Generated<number>\n  col_e245eb517472187d10441eca2c4a9aeb: number\n  col_91b6293c3ca6646fe348ce8a4f4b4c85: number\n  col_b1dc1e3377a082304d817664243e7b17: number\n}\n\nexport interface Table0e3703752e6fb26a7c95ffbf9ba62354 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table051ebef2507af0ef791ed665f9df9f69 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_20be803fa76256ebff5a3090a351dce6: Generated<string | null>\n}\n\nexport interface Tablea85ed4b894e81fcae5b5f32832c0a4aa {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_2cf1ecc054fac526249f379db15f6114: number\n  col_d2508118d0d39e198d1129d87d692d59: Date\n}\n\nexport interface Tablef2e554fc6e599ca882cad3f9c8944c5f {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  id: Generated<number>\n  col_2cf1ecc054fac526249f379db15f6114: number\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_a086a44c8be387291cb7ec589a8d144c: number\n}\n\nexport interface Table92318b69e7164d55b1815a563a4f0fda {\n  col_f32428508672211d04f041977bc90510: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_89bd8e97120bfa5bcc0fdbcf4f96365b: Generated<string | null>\n  id: Generated<number>\n  col_3e68cb4bb944a2eb1873d121e2c1da9f: Generated<string | null>\n  col_ea3e5046a32b090e4e792bb30890a129: number\n  col_98d8d6a239ae64c6f2fc402b7a7847d8: Generated<string | null>\n  col_c94ff636d78c16fd4972b7df1ed9f7f2: Generated<string | null>\n  col_fe999c04c29b51909b8ec56ecfbabcb8: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_e245eb517472187d10441eca2c4a9aeb: number\n  col_20be803fa76256ebff5a3090a351dce6: Generated<string | null>\n}\n\nexport interface Table11c3ad790c98516ecb794068e8fe4332 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_ed9174294dbcdc54c009c8087f24fd4e: number\n  id: Generated<number>\n  col_c55b5208e65984aac86ada39165d9d62: number\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n}\n\nexport interface Table0b9fd044caf91b1c9c0decf463f48479 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_6c5493e52a59d7de52511ba52276ddcd: Generated<number>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_47800dcca216b1b165c13199d66c3b63: number\n  col_3d40d536360063946092d61d8fb4af97: Generated<string | null>\n  id: Generated<number>\n  col_c55b5208e65984aac86ada39165d9d62: number\n  col_fe999c04c29b51909b8ec56ecfbabcb8: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n}\n\nexport interface Tablecb5f0e2e2a6bb82fe0ec713f3001adae {\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: string\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table05f7a75fd9ce14b6ff3abafe6a0315cd {\n  col_f606ffbc02200e165ccbe5bd6e0ce11a: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_6137cde4893c59f76f005a8123d8e8e6: Generated<string | null>\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number>\n  col_61ee96e36f87193202f69079c2a248fc: string\n  col_c010021498d7345dadc4ec5be041f8d2: Generated<number | null>\n  col_9d73dfc1b706d61e28cf50df23ad34be: Generated<number | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_910c87c70d93d69a64538ffc358a99de: Generated<string | null>\n  col_f136803ab9c241079ba0cc1b5d02ee77: string\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablef9d0cc88ca4af2fc064f9fe28c1cae51 {\n  col_258def64c72dae45f3e4c8516e2111f2: string\n  col_c50368ae5e839e9224eb0947f06fc605: number\n  col_26fc2a6aec4599af1b0a36cbe6e3939a: Generated<number | null>\n  col_aed19f4c9c98622d6661990a56b5ad95: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_ca55f5b1d19aae0a019b8afb8d995ca9: string\n  col_f9c55d34dd1668d1fc4a576fc2f8c64b: string\n  id: Generated<number>\n  col_d7cc8cbac63ee8761aabf7792b5160db: number\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_665cebec3ce1380ce4e3c90b1bedcbf5: Generated<number | null>\n  col_76ef16690bb4ed0aba9768175f242b63: string\n}\n\nexport interface Tabledf515f554daadb410af199b9d2af4968 {\n  col_26fc2a6aec4599af1b0a36cbe6e3939a: Generated<number>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_665cebec3ce1380ce4e3c90b1bedcbf5: Generated<number>\n}\n\nexport interface Tablee7013b1aa66ff80026b9594533e73417 {\n  col_0e9af2c1d8b2bdc39279709d960ee616: Generated<Date | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_de2b14ae7499f90736fc4a92327553a5: Generated<number | null>\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number | null>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_55d0da66c8f6617ffc31f4d7e9b9cd6a: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table6fc94749b5f65b04e1364bc84a3b675a {\n  col_1019e8dbd935e7e1fbaee27cb45c81c5: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_1590c1c1103e53135f348374eda74d92: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_2cf1ecc054fac526249f379db15f6114: Generated<number | null>\n  col_2c0609d963e4d588c6b53d93845d6661: number\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_74af50ad445ae874663c514314c04397: number\n  col_a1625f77580ae88538a0bba96298b5ba: number\n  col_36e816a9244e63bedbd7bac69c3208ca: number\n  col_3a4c1cab8214c2a1f85432d018ac0548: number\n}\n\nexport interface Table7e5a6e895e47f444ce7042734df8ce92 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table03fcd39a79bd9fbbc8f2f32371eb6a9b {\n  col_7844a93ad4b97169834dade975b5beff: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table3edc0e801929e10d8dd381561aa2bd31 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_e8597efec888f22158cf26c4a354b45e: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n}\n\nexport interface Table75f7cd025a872d2698d2a6e53a8cd953 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n}\n\nexport interface Table075f9410d29eaec83d4f68c3dfa82a10 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_2fd6a67502ba2fc6e63b23903522d93b: number\n  col_aaff2deb17374d1ac30c040f6f0552b5: Generated<string | null>\n  col_2931dbf568c51f5a95e2e3081491a702: string\n  col_3bf01fe7a9112bfabe3af0e2afea3e59: string\n  col_f7b98604d9635076cd6f4dd654792206: string\n}\n\nexport interface Tableb91d0a254d43344084dc0efd98b90946 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_95a573b127ca2c23a2ed1dbc7d03d29e: 'activada' | 'desactivada'\n  id: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: Generated<number | null>\n}\n\nexport interface Table4d4605d2d071f927c338880fcda7b540 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_88e292b9447efefa8460bb2b17d043c0: Generated<string | null>\n  col_ee681610cf80275688440d62a3060f1d: Generated<string | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table14a5541144254091c320909a95c4c614 {\n  col_484a106f0719881cf489e0fbd80bfc43: Generated<number>\n  col_c9774140535fe111b94e064a8c420b98: Generated<number>\n  col_662faa62e8249d797277f109de5dbfc2: Date\n  col_141e21b657ebc0212411bf8df49a57cf: Date\n  col_ce3cb2352c9bc7bfe791dc286b11e4c3: Generated<number>\n  col_d8e32557636967bba571034b4660818b: Generated<number>\n  col_5d2dad9c812862769b4a934b13695d02: Generated<number>\n  col_9b93b26c60773f04b795b6accea9014e: Generated<number>\n  col_a1cad862e5cc1c937323caa84259cefb: Generated<number>\n  col_e413d6c84d788644dfbcf3bf6fefaabd: Generated<number>\n  col_4a375049db156d117c5ad35214dfe424: number\n  col_e6a4dce7716be656ec5e052771f82d7d: Generated<number>\n  col_62b99d59be819ae40b4b89dc38d01b6b: Generated<number>\n  col_c053226db4df10c61509baef89a07cf2: Generated<number>\n  col_f9338a582beb27844ddff5a2491b29d3: Generated<number>\n  col_d3e721d3f9c12db0276ec46a3921d52b: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d86bec40de826529ed04c5d5bc0f975e: 'historica' | 'provisoria'\n}\n\nexport interface Tableb16695c526d6fa5e20b329d5eabfd364 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_2257daef930a33efc1b422d4f3d41890: string\n  col_a7743b12384fd798fdad7bff9e75bee3: Date\n  id: number\n  col_f136803ab9c241079ba0cc1b5d02ee77: string\n  col_00b4288b12a81b04c5f2479addcec521: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table9eb67e79e0e2abbb0a295904fd81d805 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_33cee772b203aed80ee06d3dcb2cbcd0: Generated<number | null>\n  id: Generated<number>\n  col_84267f80102ea16f25ffe6f5be92255e: number\n  col_b114935b452a2d927bd5ac81ad9a3d67: Generated<string | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablea700a17706246884b5a04cafcebeaa55 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_7426b7174c1b7d22061329a60b94e63f: number\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_249c850f62ea50feb918b095fc56d763: Generated<string | null>\n  col_910c87c70d93d69a64538ffc358a99de: number\n}\n\nexport interface Table6a853060686c878e7535e29bc3772d73 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_2a5b75864f31fbe839a8f028ee554f53: number\n  col_7426b7174c1b7d22061329a60b94e63f: Generated<number | null>\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_6177dfccf6065b1ec558e457a24dea33: Generated<string | null>\n  col_b114935b452a2d927bd5ac81ad9a3d67: Generated<string | null>\n  col_910c87c70d93d69a64538ffc358a99de: Generated<number | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: Generated<number | null>\n}\n\nexport interface Table2c1e8df56b265a10929de25e4593033b {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_973428953d32ee6d05ce5873c2f6c139: number\n  id: Generated<number>\n  col_2228c8ff8da091a3ba7fe63f7bf0d58f: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table3c8b015b7697cce06653b215afc8acd5 {\n  col_3886a084aa5ac96babd5443af176b2fa: number\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  id: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablef058a40da08114d390fcea4b81b4f0a8 {\n  col_cd0e40950118e419d8215d52940c0b52: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablea6a7b2d92feb037592b7ed49c34d1e54 {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: Generated<string | null>\n}\n\nexport interface Table4aba31682ab92f6f2baae3f68f9dc1ad {\n  col_17472f76c85ecf1c942560d9cf5511ba: Generated<string | null>\n  id: Generated<number>\n  col_68df1b4eeab1a558d607590173e97fbf: number\n  col_bfd8f7ddc31266f25afd1b6ea43d8750: Generated<number>\n  col_aeffdc77f4dde5fd265842bc848e92d1: Generated<number | null>\n  col_e7fa32cb05ba9ddc8d5f75bdf1694790: Generated<string | null>\n  col_9b1db7c4b5f517844f202bf7ffc3bc5a: Generated<string | null>\n  col_b53dab55eaeda66574268ffea2dd4da0: Generated<string | null>\n  col_0e46a6ad6b83de719c1b5b777e48c8c5: string\n  col_62f5fcc9ea1e44509eaecb6e081a39a1: string\n}\n\nexport interface Table75d4ed2c1cedc7a0f7e36059177a8837 {\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: string\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tablec3ba8dac5adcbeb93ed2dd458b6ad4a1 {\n  col_4ea20fbed0c11321d0d5e8c50873ad43: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tablee53ad4b421c58913d023a3296c13419e {\n  col_61949c8545b648ea08e9494e262449b0: number\n  id: Generated<number>\n  col_d2a00107fe464a6f02f9c6d81c6921f0: string\n  col_71eeffd42498c613691768b775cbf251: Generated<number | null>\n  col_f88bdb43cdad67e0a8f355a543132f62: string\n  col_5e1fe85ed4421393b4f7a7f36d69f6fc: string\n  col_b1dc1e3377a082304d817664243e7b17: number\n}\n\nexport interface Table980786dce470ebfd2621534ebcd5e6e9 {\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_f88bdb43cdad67e0a8f355a543132f62: string\n  col_b1dc1e3377a082304d817664243e7b17: number\n}\n\nexport interface Table1a270e99026f39aaf8e33546e1c2c39e {\n  col_47aba655fea8599b302f71d06d0bab66: Generated<number>\n  col_fc64eb6054f462d6d323dd7c2e2ff768: number\n  col_066a120fe3abe924fdd105d2073b3a64: number\n  col_08114ce1193bf6826c3277f27236a6d8: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_bb8f173dd39e2bbd2ca8bb502bdd5d7e: number\n  col_edc2332d18c4df92bd6c29a42e54c63c: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  id: Generated<number>\n  col_6ded30065c525d1945f38fc1b77df3fb: Generated<number | null>\n  col_f88bdb43cdad67e0a8f355a543132f62: 'CLP' | 'UF' | 'USD'\n  col_fa367b08ef9acfa2b65fc6150dee916f: number\n  col_3924f75e4f7e65a64d2f06bad0a8da28: number\n  col_885fa91590a5518eb66fcca9a6f11849: Generated<number | null>\n  col_9eed1c8dafecf36e8f11783f0f9ee8d3: number\n  col_b2211a70f2ff7369336027ed47f18f7f: number\n  col_83d043db4fdfe6882fb7f01a09d92b11: Date\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n  col_4856cff2db9bf179e997e2f57c61c649: Generated<number>\n}\n\nexport interface Table380b3be3b993931074af40f4e0af76f3 {\n  col_08de056b6d3139a95d0aaf99f8e3c52e: number\n  col_a538a4b49163b8abcdcff07958d6290c: Generated<number | null>\n  col_d87b10b303465ebc76c15dccc5cb2b83: Generated<number | null>\n  col_ed49a01549ef9030b8a17635d2c0d411: number\n  col_6d210c02b9f9e0fd7c6bb98e4b23d240: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_d7f9c190010492e516de3eebbcf3bfdc: string\n  col_d8f6edda3ad9cc2d89df66f5b6df3e25: Generated<string | null>\n  col_221bd929021f3685ea46aaa5369685fc: Generated<number | null>\n  col_15af44699327f9a6bb2f12da27fdf0ce: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_22b7922d2402e25805b18c7fa98d093c: Date\n  col_633cdd5118945d8664ed78acc276604f: Date\n  id: Generated<number>\n  col_4a1aa938bcb545cd35f50b5fb8b8851f: Generated<string | null>\n  col_ea14b84c81e7ebecb1faf4ce83b8826b: Generated<number | null>\n  col_5bff9cec94f5ab89567a1d0a24c1bfa9: string\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: Generated<number | null>\n  col_46e6bd185eb3c01ad5692d9ab01733b8: number\n  col_e66275f52358e1042acff2dc629ecf3d: Generated<number | null>\n  col_ac23115c19aea6a256fe04d9a8b6b6fb: Generated<number | null>\n  col_0191c0aa0d39de591b5236b304496123: Generated<number | null>\n  col_68dcfd901c5f8c7d467fdf74b4ac45ac: Generated<number | null>\n  col_d8ad55006c0efc8437cc487b5c5459f6: Generated<number | null>\n  col_207b11ca5edb8c143e5afe1712ecbb6e: number\n  col_8476076b3459ded88a2a4a1863b65a17: Generated<string | null>\n  col_1b6b0183f1a79f6d53cc5f8bd5f315d7: Generated<string | null>\n  col_7b7ed03cfd1bca988b56026735632df9: Generated<number | null>\n  col_ff66cc4c53cea80f652f8e4aa9d4ce6b: Generated<string | null>\n  col_6b5cc62667cadeeda2fa4f4be845e772: Generated<string | null>\n  col_dc449cf2403d7e1681944d9f4529b394: Generated<string | null>\n  col_b96e29426fd3636dd5bc9ce5b03a13df: string\n  col_195367e97caee2b9ed726514b7a38efc: string\n}\n\nexport interface Table4a03b332b99d0dab4e359b9b2e9132f3 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tableb690efdc73ab53d741824e87ddf41a0a {\n  col_066a120fe3abe924fdd105d2073b3a64: number\n  col_4f1b7b2483b9bb0a8b355ef69f09d65e: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_8f4a31364a65a9f539032a16e3f4ea8b: Date\n  col_7a9cd04d755a1c1f269ce7184b943521: Date\n  col_7426b7174c1b7d22061329a60b94e63f: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date>\n  col_fa367b08ef9acfa2b65fc6150dee916f: number\n  col_ea32f0629d5780f0b84ac3c2dc29354c: number\n  col_83750383555947e4ccbd9661a0948ffe: number\n  col_53a208b112254787b9ebe57338d2e92a: Generated<Decimal>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table80586ee503601f161507ee3f207fa19a {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table138bb88f13d65a10a42882c2578d7839 {\n  col_90ac24349411e6954fc47a05040d032c: Generated<number | null>\n  col_a538a4b49163b8abcdcff07958d6290c: Generated<number | null>\n  col_9dd1bc5c639dd9f27a30853ccf20cf02: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_62bd695be89e0f07c72268b40df9c2db: number\n  col_f514791973dfe8ce52d05f653fff009e: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_973428953d32ee6d05ce5873c2f6c139: number\n  col_74050a371c9d77e377772310c43bb55d: Generated<Date | null>\n  col_33cee772b203aed80ee06d3dcb2cbcd0: Generated<number | null>\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_48a86579578d404ad2da71aa0b2b99f4: Generated<number | null>\n  col_f61843551e5d8934a2b3afa31e66a5d0: Generated<string | null>\n  col_a48faef66299d05e03534b08993a3c80: Generated<number | null>\n  col_84169a44f95f5e872347716abd594909: number\n  col_ada72f8f1643e5c694dbf2a5636f1a64: string\n}\n\nexport interface Tablef8ad778cddf738c853992b7f5446b4f1 {\n  col_25cd93f430d277509b60d4390636895f: string\n  col_82a9e3b076bbedd5c288e8b1364c000d: Generated<number>\n  col_ebd1ae5512e18049f0c867b187ad74b7: number\n  col_c43595b745f255b38d7a1da6a7b6d5aa: number\n  col_066a120fe3abe924fdd105d2073b3a64: Generated<number>\n  col_08114ce1193bf6826c3277f27236a6d8: Generated<number | null>\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_c1beb04a7642970cf4e59164d0b162ab: Decimal\n  col_a222f017034f971d4a5004b53f0e9699: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_2a5b75864f31fbe839a8f028ee554f53: Generated<number>\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  col_d9d6c97f041fe7c54b65501f67fcfea9: Generated<Date | null>\n  col_1690e4ca8c11ef9d61ca7213686d5c40: Date\n  col_7426b7174c1b7d22061329a60b94e63f: number\n  col_0fcee78e15438d90e5191b85092b83bf: Generated<string | null>\n  id: Generated<number>\n  col_ea14b84c81e7ebecb1faf4ce83b8826b: number\n  col_7f2eeb75f4d42d42268e3dcf985ea311: number\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_5c63e943a6e825630ccaefcbed7a719b: Decimal\n  col_9c345463e1fec644c6eee8e6158d953f: Generated<string | null>\n  col_d69c485b8a1572710f1a3736bd1ac46c: string\n  col_99454795142dc6752632d6afc35ccb31: string\n  col_885fa91590a5518eb66fcca9a6f11849: Generated<number | null>\n  col_b6492f8aa398e19ecf4295c9aaf0e72c: string\n  col_08970091b0d2ad51d515d8a311e9acae: number\n  col_31f22cda5030a6e16556c8d64f4d229a: number\n  col_eb4b47c599bd30509bef47d1ea3a29e0: Decimal\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table9f6e2daac23f8ae268d4557cb47cb202 {\n  col_5a1d3fcf6b0964812cb1d9ac632408d6: Generated<string | null>\n  col_d9a3bd4bbae376e6fe20396874ab1f84: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_79bb38e8889d83eccbfe56dcb56f7c05: Generated<number | null>\n  col_1690e4ca8c11ef9d61ca7213686d5c40: Generated<Date | null>\n  id: Generated<number>\n  col_817f7773b53a20deae52a267974f26be: Generated<number | null>\n  col_678f2cb7abb9b9f59779889d38a6522e: Generated<string | null>\n  col_d0fa5f84c5a77f9a1cef6148c1a10afe: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: Generated<Decimal | null>\n  col_40772ba813d97356c66a42e44c29f2f2: number\n  col_3a5ccab1310685a8dc5a8ecf5d187e56: Generated<string | null>\n  col_f136803ab9c241079ba0cc1b5d02ee77: Generated<string | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table7ff09e5ace1dbf00f39b6358c5aa3817 {\n  col_1d726898491fbca9a8dac855d2be1be8: Generated<number>\n  id: Generated<number>\n  col_3cd6b216e8b82554eaa2f6c45b0a3c14: string\n  col_29b35b7caf7d5ae4d43b9b80ca0f9187: string\n  col_efcaf7b2db6ef497a009d28351e75abe: number\n  col_fa367b08ef9acfa2b65fc6150dee916f: number\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table3527de031c6623c0eba6355dcdd45a6b {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_52acd46049d4e8c9c8596637256408f5: number\n  col_65a3660424a0ab0c1ef22059940bd5e8: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_98c9253c0973d0e076532038838b0ad9: number\n  col_a0108f4039ad5ef8af15629186ff5d13: number\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: Generated<number>\n  col_0268179270db272c8d70e400380d7c05: number\n}\n\nexport interface Table09612d694974820d8807b91ecde8f26e {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_5d4dc010ae24f1dadd43aa67593d0f7c: number\n}\n\nexport interface Table38195ba8de22a862c0f40f70ebec25bb {\n  col_36c8e89b7e4cfc448f69c971486cb123: number\n  col_4f1b7b2483b9bb0a8b355ef69f09d65e: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_34e7aea5cf0f74ee76b3f5445a3ac1cf: Date\n  col_c84d2025f9e13529cf7b4aa05275bdf6: Date\n  id: Generated<number>\n  col_97ec9689eca8dace826b37d2ed59250b: number\n  col_3f9be60473c4a309579563a7358c92f8: number\n  col_83d043db4fdfe6882fb7f01a09d92b11: Date\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table93037210a648b88105c5ee2473337821 {\n  col_46df0ccd51bb26538db287f8e4e6e4dd: Generated<number | null>\n  col_f32428508672211d04f041977bc90510: Generated<string | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: Generated<string | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_e245eb517472187d10441eca2c4a9aeb: number\n  col_4bf016b629fc04e08a3080d945fff2e3: number\n}\n\nexport interface Table0b5857bb9e98480275f017b7af173e3f {\n  col_72f96160fd66ba04a6c4d17116faca2a: number\n  id: Generated<number>\n  col_6eabf912118c656e74717bf86ec69f73: number\n  col_32a8fa725b782b014f4fff3183a2de16: number\n  col_4289648e222b26e875a681db53d46c71: number\n  col_923c1ce4be0acf2cf56890bbd41ec804: Generated<string>\n}\n\nexport interface Tablef27ebdbd2754995818491c1018692ce5 {\n  col_1d726898491fbca9a8dac855d2be1be8: Generated<number | null>\n  col_fe7105552b616f510178c40c861ba761: Generated<number | null>\n  col_c5b4c43869f38cb5e5ca94ba8e823f70: Generated<string | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_b170288bf1f61b26a648358866f4d6c6: Generated<string | null>\n  col_de2b14ae7499f90736fc4a92327553a5: Generated<number>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: Generated<string | null>\n  col_2fcbb818ea112e40bf6f722d975e231b: Generated<string | null>\n  col_1840e20d17569bbdcae6da23c2d4efa4: Generated<number | null>\n  col_d538cbec9201a31573be8bf3b9e0e331: Generated<number | null>\n  col_a29ab34fee08d552ceddc06095b0881c: Generated<string | null>\n  id: Generated<number>\n  col_84267f80102ea16f25ffe6f5be92255e: Generated<number | null>\n  col_c55b5208e65984aac86ada39165d9d62: Generated<number | null>\n  col_c2e6b054ac1da5187e54d089c9065cad: Generated<number | null>\n  col_169ab89ce8908eabce9ec3b6c5350b3a: Generated<number>\n  col_6fb9b267c35b1007e304854b2349ed7a: Generated<number | null>\n  col_ff89eee0bc7c681adc9bc0c956a6e018: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_e245eb517472187d10441eca2c4a9aeb: number\n  col_d8b2388384ce4e4a14053e9e3c6defd0: Generated<number | null>\n  col_6c2d1e1a5e7c824f93773960c28e09f0: Generated<number | null>\n  col_4e3f97631a05a2833f3a08434a1677d1: Generated<string | null>\n  col_b53dab55eaeda66574268ffea2dd4da0: Generated<string | null>\n  col_502fd6332679b81831dba4f9517a555d: Generated<number>\n  col_85b27642c10d4a6c72c3b6b4d02c8d4d: number\n  col_3b571dce50f96585528355c99d1c3479: Generated<string | null>\n  col_1014c2beb9f5ef346656f1056d0885ed: Generated<string | null>\n}\n\nexport interface Table6009b7b4db0ba922eead74b775f40f8c {\n  col_066a120fe3abe924fdd105d2073b3a64: number\n  col_aa0ae4d63455847b0b02a481f9f38ab7: number\n  id: Generated<number>\n  col_b6492f8aa398e19ecf4295c9aaf0e72c: string\n}\n\nexport interface Tableb6b0fa946d389417c5c3f14aa8ff718a {\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n  col_ca2f68c7e7befa1bb272d18ca7a4c73e: string\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table3edf238f7262a23abe0751a2ac0af6ff {\n  col_f32428508672211d04f041977bc90510: string\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_80ae6f72f9c170f9e1bcae48c1677802: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_9de9baea781a4571ef4ec283c5bfba6a: Generated<number | null>\n  col_4649c587e02b1a41f7eb4967032e10c3: Generated<string | null>\n  id: Generated<number>\n  col_6ded30065c525d1945f38fc1b77df3fb: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_fa367b08ef9acfa2b65fc6150dee916f: number\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_885fa91590a5518eb66fcca9a6f11849: Generated<number | null>\n  col_9eed1c8dafecf36e8f11783f0f9ee8d3: number\n  col_910c87c70d93d69a64538ffc358a99de: Generated<\n    'Deducción' | 'Otros' | 'Percepción' | 'Producto' | 'Servicio'\n  >\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table55ac07dee59e4a2d00136b025cc01d9e {\n  col_f32428508672211d04f041977bc90510: string\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date>\n}\n\nexport interface Table09e8ea41829a99131a2920761d339204 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_80ae6f72f9c170f9e1bcae48c1677802: Generated<number | null>\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number | null>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_dcd12b62e76b17d69e313b8897f4f7ea: Generated<number | null>\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_6ded30065c525d1945f38fc1b77df3fb: Generated<number | null>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Generated<Date | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table7a616917b50007f39137fa41d2f51ab3 {\n  col_05f720d878e84cf5edf8810ac56f2f47: string\n  col_b599f327b0f1350c83e6466016f68dee: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_e3c09cb3d68235ebdf5820c49f6ef2e0: string\n  col_e714c1cd11c5b7d1de0c5f6e076020b4: Generated<string | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_3e68cb4bb944a2eb1873d121e2c1da9f: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: Generated<string | null>\n  col_032711695edadad1acb9974d043ec642: Generated<number>\n  col_ef1e84bf5d70755290854b1d0d60c91f: string\n  col_8b5da04bf1aacd462ab37eec2f0dea98: Generated<string | null>\n  col_c29343eaf65c23d827ee1a8df41c4c6d: Generated<string | null>\n}\n\nexport interface Table5d8df59e64a9eeca85daebca610e21a7 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_7db3960deab1cd20d8b5b1f5501f3987: number\n  col_15cf093f2ffd2ac39ed7a55e9ff65d04: number\n  col_60145e143f1a86609b62f248f3001b9f: number\n  id: Generated<number>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table526124c9359353a7e56271d12d9fcf0c {\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  col_335290b198cde5bc8fcea40f61749ec1: Generated<string>\n  col_f8356769c300813cfa84768123cbe45a: Generated<string | null>\n  col_7426b7174c1b7d22061329a60b94e63f: string\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  col_4be00234d2a8d9d5271b91c49e484dc9: Generated<number>\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_9f63df725d4f28c580e46c10f2df8a03: string\n}\n\nexport interface Table6bba2bdcbf233fb7649d1f614417da41 {\n  col_7844a93ad4b97169834dade975b5beff: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_8495897860c0b6e16a8d5c7a149d9d7f: Generated<Date | null>\n  col_1f6ae20514b228ff1f188515cde39b4e: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table390f512e2274731b2d168d8f19da171c {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_80ae6f72f9c170f9e1bcae48c1677802: number\n  col_5ba4f2b0c4324a2a400b0ae7224889c2: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_a67abae8eff833edb8b78a2ded44f0b3: Date\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  col_e9820863f3ff0a31be16598cc3058d78: Generated<number>\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_2371c6548aea76f2e1ac529a3543b7b2: Generated<number>\n  col_966c0adb6eb8c16d11aacb1b968763ed: Generated<number>\n}\n\nexport interface Table1899f801ed13e5910d18c6b08028d7bc {\n  col_030b50b01f2428db7db79395842e60de: Generated<number>\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_7364a488f431ca7296b76a34417395b4: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_ec9fee4cc043466cd4926f8982fbc146: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_fb1ecce130681efa10fd55197773267d: number\n  col_2a8da7b65d4d1b4f0cd0a3160b6706db: Date\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table1082c28dec8a8ffd8ce641335442372f {\n  col_b0ad63f3936782807cb0b2b171280669: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_62bd695be89e0f07c72268b40df9c2db: number\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_b7f9bf58bcb05c0cf59083ffb79e366b: Generated<Date | null>\n  col_7426b7174c1b7d22061329a60b94e63f: number\n  id: Generated<number>\n  col_cd52da97b57b116541458d23792b0f11: number\n  col_1d119125897e514751e695fab638cf81: number\n}\n\nexport interface Table72909a5ac37995f967b619c9cafa07d6 {\n  col_d109701b76ff710c8e7fddd648466bac: string\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_8b5da04bf1aacd462ab37eec2f0dea98: string\n}\n\nexport interface Table81a2bed79d9365d1982e76dca5a676bd {\n  col_7d00e7af094c860f729814df43ab537d: number\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_5ba4f2b0c4324a2a400b0ae7224889c2: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  col_e9820863f3ff0a31be16598cc3058d78: Generated<number>\n  id: Generated<number>\n  col_1cbcac9ade6914a00f55838acea44222: number\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number>\n  col_42efda2df902eef7402eecf653a5e144: number\n  col_2371c6548aea76f2e1ac529a3543b7b2: Generated<number>\n  col_966c0adb6eb8c16d11aacb1b968763ed: Generated<number>\n  col_8a56730bf7a7298784c796e101f92d75: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table9b567a9f0bdf26ccd8202eff33ff637b {\n  col_6e6c2420ff71849263a56ddabc5a1731: string\n}\n\nexport interface Tablecb69558ad9c32a83ec1e61169d89de2f {\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: string\n}\n\nexport interface Table69cb4926463c11065ab61382047dd490 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table3d90cba85411f05feed564dbcd2e6e55 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_aeffdc77f4dde5fd265842bc848e92d1: Generated<number | null>\n  col_10c0a78ec67f5765bb129e53d403a805: number\n}\n\nexport interface Table32254855b1a9a81426acafd370a0edc3 {\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tableccc5e7a07cecf45f43c5c4efb6bbcd8a {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_6dc961f33219b65a0c2a9287c4565f24: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number | null>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: Generated<number | null>\n  col_9d5c513c42957815f422347ca6268eae: Generated<number | null>\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  id: Generated<number>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_145e62065965d2b6e7190139880f1bcb: string\n}\n\nexport interface Tablef9ce3585ff20a0b1dd731bdd34cf0ad9 {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_4c349d7184176bbf16b24181c7d83b03: number\n  col_697b738640d40c3284f56dfa8de48189: Date\n  col_1561c874fb6b23d0cb37194fe3d8f99c: Generated<Date | null>\n  id: Generated<number>\n  col_6d2b226b7f4e0e1fbb6ec47efc9fee7a: Generated<Date | null>\n  col_9a115ebc25a0a303b3ffee1a7437146d: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_ded1e7d25d95c7702086a588883f1a40: number\n}\n\nexport interface Table1e275afc8276112b99cfc6f49842958c {\n  col_754b198717fa5cebdfd613f47444b7b4: Generated<number | null>\n  col_86a5806c9362be2f139e52bcd5e35d54: Generated<number | null>\n  col_6fbe4a892ea3ffb941c0ecf6176cb249: Generated<number | null>\n  col_00970b22f199c1f1097c435cdd756efb: Generated<number | null>\n  col_50c315b1fbd8484b7d31c7bbba602733: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_707742b6518f4d5b912446969bfc2288: Generated<number | null>\n  col_314858149774214e5c87f0dc2de8a7e5: number\n}\n\nexport interface Table24139be0f90bb33600380f06b12b7f1e {\n  id: Generated<number>\n  col_663662bf9e825d1b24e8262136d58845: Generated<string | null>\n  col_eb6047359d3711dac3175270345f5c3b: string\n}\n\nexport interface Tablee0ce7ca1270b4541c302833574025ff0 {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_1c732b74da092461cf485a899f72089c: number\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_aff776838092862d398b58e380901753: Generated<number | null>\n}\n\nexport interface Table129722fe7124ca893b45b3f11aa2797c {\n  col_f32428508672211d04f041977bc90510: string\n  col_c2673967f655e97fa0e3f979f0af8bc6: Generated<number | null>\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  id: Generated<number>\n  col_e245eb517472187d10441eca2c4a9aeb: Generated<number | null>\n  col_2af39739cc4e3b5910c918468bb89828: Generated<string | null>\n}\n\nexport interface Table361ca453b125de0694d45757ce574ac8 {\n  col_ed9174294dbcdc54c009c8087f24fd4e: number\n  id: Generated<number>\n  col_0511961bf51aa24c76ca49e18e4395e9: number\n}\n\nexport interface Table682bfd8f39f1d3c2f141f8d1bfaba332 {\n  col_53ca581ab7a5aef5b659bc27c81d5d51: string\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_e245eb517472187d10441eca2c4a9aeb: number\n  col_acfd3b262b59e5fc131811193f9fc57f: Generated<number | null>\n}\n\nexport interface Tablea4885bc4409d5d6aeca7a333deb32f36 {\n  id: Generated<number>\n  col_910c87c70d93d69a64538ffc358a99de: string\n}\n\nexport interface Tabled0b3106159632181125a90621e656efe {\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tablef8d58e2b9ad74400d9d3b73e1c56b24c {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table7f3edc307df1ebe46a26c3cdcce01825 {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table4cb9cce2545216afbbe27fd7f598670d {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table075be2c4bc1569d9e2a0f43c706845cd {\n  id: Generated<number>\n  col_146c07ef2479cedcd54c7c2af5cf3a80: string\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tableb0475c12dae1800e6f9bed0ecc74d8ac {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table9273711f2c37ed469c438c6e604205ad {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table674852753d920a7b8c85e3d7f0741d69 {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Table93fcd1b734496b580b42aff395ed8deb {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n}\n\nexport interface Tablee8de821cfe0519477927d4aceb53aedb {\n  id: Generated<number>\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: Generated<string | null>\n}\n\nexport interface Tabled97726553a6203a2e1fe24edf923c1bf {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_72f96160fd66ba04a6c4d17116faca2a: number\n  col_7e53ed5979e336b304b1d25f30e1f246: Generated<Date>\n  id: Generated<number>\n  col_024c93b9757242c6dd6b55cd2d0dd019: Generated<number | null>\n  col_9c10dc3d09f0912a7e8dc3a34d7f4cd7: Generated<string | null>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table10a7b3d08bae6a280681dd4b1b4d03ea {\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  id: Generated<number>\n  col_b1dc1e3377a082304d817664243e7b17: Decimal\n}\n\nexport interface MyTable {\n  col_6f5e1903664b084bf6197f2b86849d5e: Generated<number | null>\n  col_1d726898491fbca9a8dac855d2be1be8: number\n  col_aa4ec89520d642ef7dfed01d47c97c02: Generated<string | null>\n  col_2e66a5c7e24d1d066230f368ce8b094e: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_4d742b2f247bec99b41a60acbebc149a: Generated<number>\n  col_af4e225b70a9bbd83cc3bc0e7ef24cfa: Generated<Date | null>\n  col_4f84013a8b5e4c2b7529058c8fafcaa8: string\n  col_40e8a963a35b093731af6c3581d35bd2: Generated<number | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_454ff479a3b5a9ef082d9be9ac02a6f4: string\n  col_286755fad04869ca523320acce0dc6a4: Generated<string | null>\n  col_164b7896ec8e770207febe0812c5f052: Generated<number>\n  col_3917508388f24a50271f7088b657123c: string\n  col_6f7a0a5f582c69dd4c6be0a819e862cb: Generated<string | null>\n}\n\nexport interface Table5e096b65e80874785e32076304380404 {\n  col_033f9699cf99d7dbb6abab6ddadb5984: Generated<number | null>\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_de2b14ae7499f90736fc4a92327553a5: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_9d73dfc1b706d61e28cf50df23ad34be: number\n  id: Generated<number>\n  col_1cbcac9ade6914a00f55838acea44222: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n  col_83f7d7a27d3135c03186f950e68e1f50: Generated<number | null>\n}\n\nexport interface Tablef3ed8107e22455983dfec1061f270c5b {\n  col_2f76db193eac6ad0f152563313673ac9: Generated<Date | null>\n  id: Generated<number>\n  col_d2508118d0d39e198d1129d87d692d59: Generated<Date | null>\n  col_c5cfca6ce5a95940c658d8d972f0ba57: number\n  col_cb1fa9fed74f1879504442547a142c1d: string\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tablec051ae09c6cf6d7d3ea3732241b7ec9d {\n  col_5e0ed9fb00ecd0c6dd65a18eb7e113d1: Generated<number>\n  id: Generated<number>\n  col_d8549244769c9dc8a8cb8382a54feace: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table58d873381dd856073dc8af727f75a83c {\n  col_a538a4b49163b8abcdcff07958d6290c: number\n  col_066a120fe3abe924fdd105d2073b3a64: Generated<number | null>\n  col_08114ce1193bf6826c3277f27236a6d8: Generated<number | null>\n  col_4f1b7b2483b9bb0a8b355ef69f09d65e: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_80ae6f72f9c170f9e1bcae48c1677802: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_65412d203d0de8b88fb8688cc686a44e: string\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  id: Generated<number>\n  col_6ded30065c525d1945f38fc1b77df3fb: Generated<number | null>\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_5607e33e4ae68a12af15c4fa9ada5c93: number\n  col_a7d0a8fb2a80ce50003c37428903c871: Generated<number | null>\n  col_d721d91f1a957bbc273b111830ea9355: string\n  col_aedc0cb96fca54b979311e9caaf1345b: Generated<number | null>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Table2efbbc557d528fa0179d8200f20bd375 {\n  col_066a120fe3abe924fdd105d2073b3a64: Generated<number | null>\n  col_08114ce1193bf6826c3277f27236a6d8: Generated<number | null>\n  col_4f1b7b2483b9bb0a8b355ef69f09d65e: string\n  col_2f76db193eac6ad0f152563313673ac9: Date\n  col_80ae6f72f9c170f9e1bcae48c1677802: Generated<number | null>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  col_33cee772b203aed80ee06d3dcb2cbcd0: number\n  col_35ccfc3446d7aa0609cab70e86d2b448: Generated<Decimal>\n  id: Generated<number>\n  col_9859f83dd80f56deebeb616b6b575ee3: Generated<Decimal>\n  col_1cbcac9ade6914a00f55838acea44222: Generated<number>\n  col_6ded30065c525d1945f38fc1b77df3fb: Generated<number | null>\n  col_b114935b452a2d927bd5ac81ad9a3d67: string\n  col_d2508118d0d39e198d1129d87d692d59: Date\n  col_fa367b08ef9acfa2b65fc6150dee916f: Generated<number | null>\n  col_5607e33e4ae68a12af15c4fa9ada5c93: Generated<Decimal>\n  col_aedc0cb96fca54b979311e9caaf1345b: number\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: number\n}\n\nexport interface Tableb1c2cd01d00c7351140f576d84e64fc1 {\n  col_7e53ed5979e336b304b1d25f30e1f246: Date\n  id: Generated<number>\n  col_fa367b08ef9acfa2b65fc6150dee916f: number\n  col_e245eb517472187d10441eca2c4a9aeb: Generated<number>\n  col_b1dc1e3377a082304d817664243e7b17: Decimal\n}\n\nexport interface Table173d3cc6670ed190157f57b6fc5f789f {\n  col_80ae6f72f9c170f9e1bcae48c1677802: Generated<number>\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<string>\n  col_a7f4797b61012da3a9c1a8049c8a4974: Generated<number>\n  col_6c58e53058059892b26b3562a7fafa9d: Generated<number | null>\n}\n\nexport interface Tableea7fc406759eeeabe58177f5dc5b2749 {\n  col_80ae6f72f9c170f9e1bcae48c1677802: Generated<number>\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<string>\n  col_a7f4797b61012da3a9c1a8049c8a4974: Generated<number>\n  col_6c58e53058059892b26b3562a7fafa9d: Generated<number | null>\n}\n\nexport interface Table5d31333676303c399518c2fc4cf6ce6b {\n  col_80ae6f72f9c170f9e1bcae48c1677802: Generated<number>\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<string>\n  col_a7f4797b61012da3a9c1a8049c8a4974: Generated<number>\n  col_6c58e53058059892b26b3562a7fafa9d: Generated<number | null>\n}\n\nexport interface Table411a4da56c483124eeb78d27496b6bcc {\n  col_80ae6f72f9c170f9e1bcae48c1677802: Generated<number>\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<string>\n  col_a7f4797b61012da3a9c1a8049c8a4974: Generated<number>\n  col_6c58e53058059892b26b3562a7fafa9d: Generated<number | null>\n}\n\nexport interface Table90b86be76e1fe1dcbfeb23aac1268f60 {\n  col_80ae6f72f9c170f9e1bcae48c1677802: Generated<number>\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<string>\n  col_a7f4797b61012da3a9c1a8049c8a4974: Generated<number>\n  col_6c58e53058059892b26b3562a7fafa9d: Generated<number | null>\n}\n\nexport interface Tablead803551807f7dd640a7431281e60024 {\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: Generated<number>\n  id: Generated<number>\n  col_0169d667d30453fc6d348ede68c6137e: Generated<number>\n  col_2371c6548aea76f2e1ac529a3543b7b2: Generated<number | null>\n  col_966c0adb6eb8c16d11aacb1b968763ed: Generated<number | null>\n}\n\nexport interface Tableacd9c0e145638abbf38c6c9982b5d978 {\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_0169d667d30453fc6d348ede68c6137e: number\n  col_2371c6548aea76f2e1ac529a3543b7b2: Generated<number | null>\n  col_966c0adb6eb8c16d11aacb1b968763ed: Generated<number>\n}\n\nexport interface Table03d5e3f6a5a1305f36b6f5e7b40f8607 {\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_0169d667d30453fc6d348ede68c6137e: number\n  col_2371c6548aea76f2e1ac529a3543b7b2: Generated<number | null>\n  col_966c0adb6eb8c16d11aacb1b968763ed: Generated<number>\n}\n\nexport interface Table1ad14a94caab8e7087a497085d7136ee {\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_0169d667d30453fc6d348ede68c6137e: number\n  col_2371c6548aea76f2e1ac529a3543b7b2: Generated<number>\n  col_966c0adb6eb8c16d11aacb1b968763ed: Generated<number | null>\n}\n\nexport interface Table13e2dfe71a6146bf0f7286309cee804f {\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_0169d667d30453fc6d348ede68c6137e: number\n  col_2371c6548aea76f2e1ac529a3543b7b2: Generated<number | null>\n  col_966c0adb6eb8c16d11aacb1b968763ed: Generated<number>\n}\n\nexport interface Tablec227d3e74b291218da01d96ad8e3cbf3 {\n  col_b44e675732d485b4ded87fd63200ab77: Generated<number>\n  col_c010021498d7345dadc4ec5be041f8d2: number\n  id: Generated<number>\n  col_0169d667d30453fc6d348ede68c6137e: number\n  col_2371c6548aea76f2e1ac529a3543b7b2: Generated<number>\n  col_966c0adb6eb8c16d11aacb1b968763ed: Generated<number | null>\n}\n\nexport interface Tabled861babbb2f5fa7cd7537704e5000a83 {\n  col_c010021498d7345dadc4ec5be041f8d2: Generated<number>\n  col_739f751f517ccb895cb948a88ad78e43: Generated<string | null>\n  col_1a1bd05bcd142859a62686952940e09e: Generated<string>\n  col_b0da1cb2ad234bc279511b1fb66f6fbf: Generated<number>\n  col_07b081464f537fa90b1de74e33d9f823: Generated<string>\n  col_2b9cb9ef1a2977920c1ffd5df4bd4817: Generated<string>\n  col_9d73dfc1b706d61e28cf50df23ad34be: Generated<number | null>\n  col_b29a1ebd32df20c0b7928f43baa738ee: Generated<string | null>\n  col_1aba85bbebef5ff4eee2f59cb2d9d7b0: Generated<number>\n  col_0b683b909d42220ecd33ed3752ac705a: Generated<string>\n  col_1e8e291fd8d42e9948004ae41f09dece: Generated<number>\n  col_4241cfa1d3605ca1ae3b0559e88e1eb2: Generated<string>\n  col_aa6b7c7a9c7a177e3f1ba452783eb63b: Generated<number>\n  col_93fbfd598e9de1272e10942d7a5cb6ad: Generated<string>\n  col_13a88bf9e5fc7bc33fd7d95a8bce65ba: Generated<string>\n  col_484ada59e3bc5009053ee3de7238e81a: Generated<number | null>\n}\n\nexport interface DB {\n  table_87d275947b3f2a646cd8ee94f591ef86: Table0ec723c3d4ee7229ffba2a11539b0129\n  table_cc84d0da913ff5e201cd2498cd11bb90: Tablec67d8be002857dd3a70a2c4edaa4671a\n  table_49830d6d58c2b4f748ffc67b8b96d2ca: Table3face097074d5d4ea47610accdd3ffc1\n  table_808edb85a0b912066126738aee81e217: Tableed617265d2d72c8e748ff8796bfa04c4\n  table_53425a83056f97f81ebbed0e3a7c3de9: Table6dc0e4bf3b08bdf7391e5d833d1673d6\n  table_736d84cc80e257dc78371b1eb0fb6b20: Table2f01d1d7b29ae047871b62964df1ecc3\n  table_487e1ea19a552a812641fce4b25ca0e4: Table9f50dbe0b662b9cea0d016836eb72504\n  table_a54c27458b6b5713e6fb731d2d54c2c4: Table4b8e90e811d962e132f9550bc90d5443\n  table_ed9c00f680d2f0160414e2616694a04a: Table0ae6c699b7b44b166093c052150a0d36\n  table_9996a55495fbffd1989dc4542469aaeb: Table2e45370c867ddf8f0ca7710b63dd2746\n  table_426cfbb1cb47118dee5d9aeb9ebc9811: Table19f57540d944441abc6dcebc976adf96\n  table_e5cf1dcc3993bf7c0ca2ce7e2f1260a5: Table1d1b84f13a74383d5b0324a011b609c6\n  table_c5a8b59778733a9ed1ff55b76feb5aee: Table42dbaa8105cb92599360aa5169283403\n  table_4f88999bf83d95515d96be5a0060a387: Table2f81c25612f8fefd026b753a1753974a\n  table_e0290dd8ecb360c47044a3a2a882dd6f: Tableded2bdb12664e58a26152ebb5fe676bb\n  table_2fec9061cff5d6a33870e59fcdb06c31: Table23e7a1e5ab953d2a85a5958458d0d824\n  table_aae67cbd807d09b0d66e062e70f886dd: Table41bb6a93b802fe08f0b054ae835e2fe4\n  table_d1bd6a4f6d21595e92f85d647b668e64: Table8be6c29eada2e2ef68bef0c9c1401a97\n  table_8be60df8bd508aa3b21a02c30f2d540e: Tablee91e54a2c273ec3221b4d98ae8d79d12\n  table_a489899852f5f4a4a8dd760a53cadf3f: Tablebb08e5d0fa8fd6089eeeb1ba950944a1\n  table_157a3bc9c27097f32f4faeb89768cfb1: Tablecaf406ab258ff4b54413265206d55b45\n  table_975382265709d29c3f2442e3bfb74935: Table90ffcbc2bfc57b68acac037b0aeae3d4\n  table_ecaa5c884efb077761e66b71833b253a: Table1e2c9919a848fb2673ac28780aba041c\n  table_6c06b705ee850005c02ffbe38262ef25: Table1c765aad5af6c98fb0ef475fadda911b\n  table_1b322cd0c444c827dac7f30ae058a2be: Table4f240fba2b420e220c97e6e14c4819c6\n  table_3ae4d1acdab97e1ef170f779f41ffcce: Tablec97e3cdd896ff553853d7817e4a866e2\n  table_4a9207b1eeb4f40952b69f3479a48037: Table4974bbdf9d728fb538d7507cb9f84842\n  table_610862f4ec87086144fc1485e6838505: Tablea3c8286fc7df926fbf05e09a03e2ac77\n  table_fe1a1676504a5a83e3fbf40eec955a58: Table39bdacc8b55267ffc8bf75ff8ec564ce\n  table_9d71d7aaffb66d31bc2b9b42a8ff2edf: Table3d68aac4deb5f76aaffa0df8c01e305a\n  table_6c94f280d7ed171b4ae6f181c9731c34: Table90a64fc3cea5bc905374973771cafcd3\n  table_d8dae30aa04afffe6c328708f46ec44d: Tablec479a580bb37024884d940eeacc9c4aa\n  table_9c3e72d53ff7007af15c6f696fb71812: Tablef7d7a7557d9db50bd40fe14bd830b9d4\n  table_81985582f225312b575afc02878085dd: Table1d62a6c4a9763009cda042181b0c48af\n  table_aa3267f05fecf061f13699e786a51f9e: Table916f65bd1433290f26613ccd976c68a7\n  table_11ede743d16afa28cc84bbeadfaa538b: Tabledb34593d7377d2007d44ba4b47dcec97\n  table_af0437a4a6189de08d668a2d0ce97b54: Table309c66af6ff8ccb2dcf123e1af40c9c4\n  table_98573ae89696f94f48a44b2b079b64f8: Table8921b63f9cb21e8293a8c1ddd9edc866\n  table_7980538dcc93de25b4d83b4b3261ed3e: Table2037e68416ae40369fba0a939e7ac693\n  table_6d3142ac2a560a1c5c32e699f81bf7ba: Table2b3f160083004c6c92a2ce1faf87067d\n  table_b37880f0bb08f83da5de92e1efa19943: Table5135075fea7b2d1c93603df216620907\n  table_59aae399ad0526272d45ea6c030d0daf: Table5d4433ff31ef75511e70aa6e71495afe\n  table_6fbe4a892ea3ffb941c0ecf6176cb249: Table9e258b1708bd64e877d6cca1467dee66\n  table_fd70d2cc35269b186dc738d8a6ba8324: Table4ed17d356988e97fe63e4b4e3b060917\n  table_8d8d4b505b94c6f16ecea33984d5c60c: Tablea95d291bccf0be8becb18282bcbf93a9\n  table_fe15a427dc1402f37002fb019dcb3607: Tablee12f5b7476cba16c3b1480cd551d2b42\n  table_e36a272a216738299e30a9823c9b0502: Tablea6ca43be611a38117221fef4c761f97d\n  table_977e92e9417068febe7a1207f0ee014f: Tablef83eda9e66948a4da342fadf183e32c3\n  table_5f9639fff5d140e880cfe248f297d49c: Tabledfc2f0e19fe1c0e8dd04191a3035bac8\n  table_d5c1fdd37d3bf68fe20c43ca4520f7b8: Table93f030da0924f35ab2e57081dad1e2fb\n  table_03c2b698e69f760082f5d99cf50fc7cb: Table59fc5666d6be52faaeb255fb48a401ef\n  table_2e7acdf58c80018a69ea3ff6d311d5e9: Table29c7f8f8df026c49d8ea3ad088e8780a\n  table_5e34805f74fb904a4f6c1cb475154d11: Table2e5e86f744edaeea91caedf4496cd21e\n  table_26eae7010f00790dcb9fcea51b458b20: Table27112b32955bc32b3cf3abc78f6041f7\n  table_5a7765fcdd3e8de9d430693787b3d7e8: Table6a8129f282adc469ee9233bcf63f20b7\n  table_0be8b4549e9512252af1761de32647d1: Table55cda7b389c3f5e26b58e806dc82d6cd\n  table_5a161ff0fcf3e07c472290ed26b22b88: Tabledddb567693b67dedccc76feeaf305885\n  table_1787f968ce9e996c38ea93516367e7d9: Tableb45f137169628885a5507a98a1fd203b\n  table_59aa2c8b41281fdb8918df77e2d7f549: Table4d0fb43fef8f71d027e1c62ff7b83c1f\n  table_7c73f0112ea394abeaac85d07c32c96d: Table26d9e67842818bfccbbfca6020d3441a\n  table_1c0b897074552cc11aeffb1cd2023038: Tablee6de3a3fdf132b2b794ad9358fe01719\n  table_7232d71e7a31c3959d4f9758b01bd87b: Table5bdeb7407d8776f9295b3ae2eb482855\n  table_c5b4c43869f38cb5e5ca94ba8e823f70: Table259a82d9d67d1b779666191753027e2d\n  table_ed7ed6a3c5b4edbc5cb93ba6ccf845b0: Tabledfcfa50cfe70d46b898ed0fe276855e4\n  table_00970b22f199c1f1097c435cdd756efb: Table11e00101e1b2f60d0a2acfcf46151908\n  table_a7991c3173c68564fa7034c40ed76e50: Tableaa828347830464c8d6fb6070585f8786\n  table_81342351d9b0750a6a1867e61a69f57d: Table5e1a250360f2e59810faaec5dec74bfb\n  table_20453ddb146769fa6cfbba4518a94e35: Tablecb67af6a70220cf4b2c4e1121d9351c6\n  table_34062ca76ff4de600cd82d2867d743d5: Table01687ac6f71bbab86d7fb8482bf71301\n  table_5bc008425c0529ce7f1bf46b23bb12df: Tablee4612831426584576f2d39997ccac9c8\n  table_44b3b2fbc1525a37fef79e3ac36ae137: Tablebca1b3f3c2526216b2f01c01fa85f3f9\n  table_ac000b4f6f0f6a63f812a54a2fc1d54d: Tablecac2eaeb16e94e019e7e98240c4bac17\n  table_d9240bae841332419073d023ec9d7da3: Table7eb5460a0c6690c1dff53fe4940240db\n  table_7d2894dd74c1eb98e683d83cd9f5e554: Table5c88bed5704d2054a84d44150bf10f21\n  table_3c21e15fe7f88da04c6eb6546f1f0c45: Table148eb9256ed9e01df75e345bd7e5c9f7\n  table_1f2e67e4f6060a2f4483f85e11e9a4a0: Tablee2c77a8b952bdea3bc2cb7261168ec45\n  table_9eaad0288ab657d15b0b89a9b118295d: Tableabd2380e09dc7a608bb7e5c33654540e\n  table_1a1463b3e26cc157b5bbbb8fde616025: Table7117bf3bff290101f4fa6d6de627b58f\n  table_7349c3b05f3dfb291a9a73aecd2d61a0: Table202a1f7684d2c58afd3885112de82158\n  table_2e34d0c29c1107b75c385543999c12eb: Table93aeee94c0d8d4e08a56c97185d68ae7\n  table_06d62f58421acbf930a661bbd3ce7452: Table70c085cf2d0edd14f7dbae474f064b1c\n  table_aad0e25ecf17545e7bec374e476f9b47: Table2b11443e8af088b453d5119d135803ac\n  table_ea23a0a1382ceb403c98dfa1a709b361: Table0a542ca892cb0eea27538d7360f718ec\n  table_f84e347fd6617acc6a0f6a8973248874: Tableb8378493b92a26626ae5745222c8ba69\n  table_1adc14dc0a7ec969c3e77d40758cd493: Table565a308ecf3782bb5eb0197187361913\n  table_292a9ebdda857f983a6fe42a2c434e05: Tablede86128413dcd68bd6d1ca009b6bae17\n  table_36992d0f70a50b1b2ffabb5eea57bd1b: Table57dadc25e9a34c53f66b5cb499d75904\n  table_268590e60e51ec5d0b870c82481f2b2e: Table366c7f7bccaea5ff455a9b9265448ebf\n  table_132d4b3547909bc6256d34163fb57eb7: Tablea4ca5018c98bd7912524f97ccd0a8757\n  table_c7c8d495ce776873a2da62c508138d34: Table402dd89f94d2a88ccdf049224dfc8700\n  table_70aaa597ccbbd5cd92d99b1cfa7c8b1e: Table92498a6babb7032cdcad6e43158a3359\n  table_028c49ccb95cbef10c800198d6d80928: Tablee90356817b37536144c4cf962e9e5165\n  table_3d3048db19a6783cbcd9a6ced2755859: Table61a79fc440f7ca2d4190d47ee809f66c\n  table_b900a90f5f896392fbb4c9055bf75465: Table7051320fedfb456818eb15cdf217186d\n  table_c1beb04a7642970cf4e59164d0b162ab: Table2d7cdf1ccac4544f81ac78a12d5fba7a\n  table_8cdd0973d9ca586415d14a8f279149a7: Tablea8e3bfebcd001eac1185867f7dec94a5\n  table_50c315b1fbd8484b7d31c7bbba602733: Table148ce21c70970d2809c4028c229445be\n  table_a4492608b8eebc6dfc51867d1829953f: Tablef650c769203b8bd7eed5a8b7e249c0a5\n  table_46cb140f325195b7e28886910ba67990: Table8b9070a970ee019dd472ce6c4a08418b\n  table_ae8048f57d533f1206ddaff81f6258d5: Tabled580c05f239408ff0392e235078a0ac9\n  table_dad30ddb3ecff3c395383e834f041676: Tabledd7d780df70068dcb36a8d8b86bd5298\n  table_d6303bbcbeb3da317670fbb8167bfa1d: Table48df920caa8cc60fd47820e9d94ea940\n  table_6611f9ee209aef523c4dcde78383a3f1: Table9bb0301f7ca02953fac2add8dcd7630c\n  table_8d9107a07a519a3e02e2ce5e0f68bd8b: Table5492e76278a71210d7231f4bf905ec2f\n  table_9c0640720d7b649f506ca4860e443f35: Tableea8e45026529937b0cecd544d8801cfd\n  table_ab478c8f5bc3681081805bcdc6e4d0c5: Table574ff9acd571619424cd55716f5f1dfb\n  table_92917d401ca6fb8bf405fd92c407fc13: Tablea79aeca54482635868f02356a51fa369\n  table_a68acda553f5f089df441d59eeff1d9c: Tablee7a44a84d410fa64377504e3aa7f72b6\n  table_99e321b176fbf3589a92e6084f6c14d4: Tabledcc9250fc52d5fbc25a56cf9c4089073\n  table_7518c800f93e5459daa1ff73c7fba821: Table4d82bf6c52ed1355768c73593994c5c2\n  table_49781987f16dbfbb517b355b5e7f82b9: Table73f359bc2658d254af39135aed8c3bf2\n  table_76d040ce360ee5b120a40f7066084137: Table8cf85c63dc3200ef8145fc0344d00f16\n  table_e89504d58e9f3da99aa4c0e6c4284088: Table401ef7ed8ddaa97932ede0de0b157c04\n  table_5ceb5499052a2078ef4fce93f69467f8: Table3e875ede7feab48a89082e0c87c364f0\n  table_025ad7e58da04ed8536959ba4103b6ae: Table7822bcc86140bf34bc6cdacbd734c0ef\n  table_312cefebb95f0e122bc9915cc4159167: Table459dc31349051f20a755552adaf60c81\n  table_fff4c6195261874920bc7ce92d67d2c2: Table1b8610f190607dfbdafa9c71f72acd43\n  table_02bed0f193a8ec672c01e4c7da096850: Table1edc1b921ba66176c3ec62961c248f78\n  table_a5fe391b0937a21fdd489d49b271167a: Table9b72afad4afd63d81ab6ef56c926765d\n  table_17f5074d56437c231c6541a447d3ec23: Table309e0b9a80a4ad911a672f7174429e35\n  table_1d97d2be8972551ff4d686c373055915: Tablea0eb46b195e5cbd5e85384a9a1622c14\n  table_7025bf2bf5e2e0d6a4487fc0cfbda364: Tableea5b8f9c56ff4ae4cb3c8f22541b33ba\n  table_50b53baf2b58394268ae89bddaf7c095: Table3a87f98012aa2362e8eb64ed4d9e8f65\n  table_50430e0942ebf25480aa9da4b89279bf: Tablefe2e32091534caf00911fc7435cbc97b\n  table_86e46f16f4e6a386a521c67241d2d42f: Table3cdcee0d77b622e8a2ec654a21270877\n  table_a697494b3fdab0b4e126bd3a64e9f9c7: Table8077f242ad5e05394a3dd81ce79565f7\n  table_6e128f9931a1632c258c1281fdf4636e: Table52a8644bfd17799495525f2fd8adc480\n  table_b43f07de70bf895db779f5f97cb8d105: Table74bb684c41a71a06f561e10ffa4e3323\n  table_dfdf6321467f7b66dd8ad7b08e1d54e1: Table64ac7b9a171e9af222924b693d44887c\n  table_6c334f6291be7fa62a9aca0feca9da96: Tablefd230cdd0c0d7bc04b06cffa3bc3fa3e\n  table_d4391454b38c50461bc8606d5dc6e203: Table2bf8003c7e2a7344f4d30c3a351926c5\n  table_d35939386c5c0d22ce7f7c32e8646e0a: Table5c1f23359d009924d75dac9200da99ab\n  table_82a555b6d488646ce24524e71bb056f5: Tablea6cdaf7c2c1c27d8389fb8ec7831b240\n  table_bb0744a0bc7973cbcca7a79bad78451e: Table618b14672aa41a4ddbaa07b4668e9ceb\n  table_707742b6518f4d5b912446969bfc2288: Tablee0ac1a12db533e45722bf75854c5f68f\n  table_99ebe26a1b9b9b2bf0ae1e00435dbebd: Table6b64130a9ac5e9179051a15684e76956\n  table_0f9e8815806e611d4c51af6a6e4f1a0f: Tablec3c4b9ba46ff23ee52e9fa59ba4cbd42\n  table_81ae6fb42f5779dfbad0a06795277f3b: Tableac8f964f7407177bed83d5a1b563c4be\n  table_ac0e4fab912414bf6c4d82ca5e679862: Table0e3703752e6fb26a7c95ffbf9ba62354\n  table_6cbf92b1a3e27faab6982aafe47bc0fd: Table051ebef2507af0ef791ed665f9df9f69\n  table_ffd3383867c4ae4d8c200d3c09006427: Tablea85ed4b894e81fcae5b5f32832c0a4aa\n  table_4566a5569c4fa2c2ba07bfa6b8397135: Tablef2e554fc6e599ca882cad3f9c8944c5f\n  table_8bf9d631744222f061702b22effbed68: Table92318b69e7164d55b1815a563a4f0fda\n  table_fe3fd6febea537a97cc193cfaef7aa05: Table11c3ad790c98516ecb794068e8fe4332\n  table_af3d9c9d6bb7af18c920bc8963996ba1: Table0b9fd044caf91b1c9c0decf463f48479\n  table_eab40d2792fcf58cdf6d56df7c676d02: Tablecb5f0e2e2a6bb82fe0ec713f3001adae\n  table_81859a5a7cf340e00333e133ee83c6a3: Table05f7a75fd9ce14b6ff3abafe6a0315cd\n  table_5b6c09d8090e38e65507dd7138348724: Tablef9d0cc88ca4af2fc064f9fe28c1cae51\n  table_1084015020d8bed5c99852780cd060b5: Tabledf515f554daadb410af199b9d2af4968\n  table_56bb19565d266b3c5db4b36b54121de1: Tablee7013b1aa66ff80026b9594533e73417\n  table_fc8beec5010138f14cac210396ce946a: Table6fc94749b5f65b04e1364bc84a3b675a\n  table_b1de95565fefb12c1b5e9ced0c31aaba: Table7e5a6e895e47f444ce7042734df8ce92\n  table_7ee33378e7a9581242b177c22d55035c: Table03fcd39a79bd9fbbc8f2f32371eb6a9b\n  table_889380bbad7db8828028ff1756840b4e: Table3edc0e801929e10d8dd381561aa2bd31\n  table_a89ef28d2e368372d285517fbcd8c8ff: Table75f7cd025a872d2698d2a6e53a8cd953\n  table_3176e3c369a24003ab8f6bdeb5e36fb7: Table075f9410d29eaec83d4f68c3dfa82a10\n  table_28536ba4b4a961d66303d15d863e9bbf: Tableb91d0a254d43344084dc0efd98b90946\n  table_905ec07246a5e10d75f1ec0c71c1cbb8: Table4d4605d2d071f927c338880fcda7b540\n  table_649ac5d5790cfd996132f99bcae54699: Table14a5541144254091c320909a95c4c614\n  table_9034bb7c1383ffc26a086c9da4db9f44: Table9eb67e79e0e2abbb0a295904fd81d805\n  table_5cc5636d8577bebe57cb65d9f80ccf60: Tableb16695c526d6fa5e20b329d5eabfd364\n  table_943bf2c7f95a1de4c96d117762255431: Tablea700a17706246884b5a04cafcebeaa55\n  table_a99e53e8b0ea6fb028b8335f6879b541: Table6a853060686c878e7535e29bc3772d73\n  table_dbdc90d2efd6251b1dc89255b5547d58: Table2c1e8df56b265a10929de25e4593033b\n  table_011ff64548a9d77b1672d61c71b144cd: Table3c8b015b7697cce06653b215afc8acd5\n  table_7dd9f7bddf3aaf04099d008f1615d84d: Tablef058a40da08114d390fcea4b81b4f0a8\n  table_91ae77857e698e702b1d36d8086e94a4: Tablea6a7b2d92feb037592b7ed49c34d1e54\n  table_5e350d0500edbf693ecf31bc420dce10: Table4aba31682ab92f6f2baae3f68f9dc1ad\n  table_986fcbfdf73cf8637d5863efcc4a23b7: Table75d4ed2c1cedc7a0f7e36059177a8837\n  table_87b2787be746d9af6fa1f02c7174b6de: Tablec3ba8dac5adcbeb93ed2dd458b6ad4a1\n  table_adebe9d523b0e904d5a23244df8acc86: Tablee53ad4b421c58913d023a3296c13419e\n  table_0e3a2fd2e1be1fb139d982cc4cf27a37: Table980786dce470ebfd2621534ebcd5e6e9\n  table_044c3ac3bb3a8f36c94c6914fec4c640: Table1a270e99026f39aaf8e33546e1c2c39e\n  table_0b5ac72e03509e06683edcba4b3887ab: Table380b3be3b993931074af40f4e0af76f3\n  table_2746d6a0415f4e97db91054eaad8f549: Table4a03b332b99d0dab4e359b9b2e9132f3\n  table_c3489d7044badb74bfa78892e5af3c50: Tableb690efdc73ab53d741824e87ddf41a0a\n  table_27157dcf07c6222108aee0ad07fc3c84: Table80586ee503601f161507ee3f207fa19a\n  table_9616c4051420073951c9dadfe4cfecd8: Table138bb88f13d65a10a42882c2578d7839\n  table_382969f15d228ca40eaaf6ae3af42dd0: Tablef8ad778cddf738c853992b7f5446b4f1\n  table_ba15c662ce189e01e69a2426db41e884: Table9f6e2daac23f8ae268d4557cb47cb202\n  table_ef0c79ab9a79c6eedf5a3738c59b4e35: Table7ff09e5ace1dbf00f39b6358c5aa3817\n  table_737ecf944683adc260346e8cc807a707: Table3527de031c6623c0eba6355dcdd45a6b\n  table_38773f13c7c7902bd4b3717a240873e7: Table09612d694974820d8807b91ecde8f26e\n  table_1a55586b73d1a759c1eadbafd3e87c2e: Table38195ba8de22a862c0f40f70ebec25bb\n  table_de936835b986b7e9a72b8706204dc183: Table93037210a648b88105c5ee2473337821\n  table_1ae34354f4623d6118be8b39a6c33401: Table0b5857bb9e98480275f017b7af173e3f\n  table_b1d00f154cae4b5689f1c60fd746cc6c: Tablef27ebdbd2754995818491c1018692ce5\n  table_5dd25bad4af1a1b2e85d63d182300992: Table6009b7b4db0ba922eead74b775f40f8c\n  table_d119c7e31c78a3c779aae46a89f48594: Tableb6b0fa946d389417c5c3f14aa8ff718a\n  table_1c9d336338cae6fb14a0990bd1c54bc7: Table3edf238f7262a23abe0751a2ac0af6ff\n  table_6b6b30980569c916119c335ee3ecd6fd: Table55ac07dee59e4a2d00136b025cc01d9e\n  table_c5c92cab080fe1234767a8be5814e634: Table09e8ea41829a99131a2920761d339204\n  table_0556e22da4d46d9d6f4f679de33c729b: Table7a616917b50007f39137fa41d2f51ab3\n  table_d1b04d199a69310996ab11fa49aebf4d: Table5d8df59e64a9eeca85daebca610e21a7\n  table_03fd35f2b6a928e66a8894f914fdeb1a: Table526124c9359353a7e56271d12d9fcf0c\n  table_18563b6f693d0c3e17d63aad91681eba: Table6bba2bdcbf233fb7649d1f614417da41\n  table_5d1d4bbd5ec1f145b6fe12b78aa0a2ee: Table390f512e2274731b2d168d8f19da171c\n  table_c1069472c40f0480a45ee4dee787c4d1: Table1899f801ed13e5910d18c6b08028d7bc\n  table_b20ae4cbae25a95b31299dc9033fd532: Table1082c28dec8a8ffd8ce641335442372f\n  table_5761eb47c363bdcf7bbf68c1801bf699: Table72909a5ac37995f967b619c9cafa07d6\n  table_404d5ee6f26bda1b4be093317b500097: Table81a2bed79d9365d1982e76dca5a676bd\n  table_e8e1d616dac945e0ee0d05480ab77957: Table9b567a9f0bdf26ccd8202eff33ff637b\n  table_de8db519594b7d21efea9f31260b2423: Tablecb69558ad9c32a83ec1e61169d89de2f\n  table_735c26d97cd342c6161c22f66cc99511: Table3d90cba85411f05feed564dbcd2e6e55\n  table_cf38d23f2daeff354349485b97299972: Table32254855b1a9a81426acafd370a0edc3\n  table_92df6eeac3e4b00edeee9dfe99d6640c: Table69cb4926463c11065ab61382047dd490\n  table_fefdea6d099a9810a67b711700a35a8d: Tableccc5e7a07cecf45f43c5c4efb6bbcd8a\n  table_a3cb20d19c33e8fb3b00b07fba07def0: Table1e275afc8276112b99cfc6f49842958c\n  table_d5db6cc36112076d805e58cb5ec13850: Tablef9ce3585ff20a0b1dd731bdd34cf0ad9\n  table_dc93e59ae64c8cdae881b6f25d64564b: Table24139be0f90bb33600380f06b12b7f1e\n  table_6efc03d13cdcfd25a9ce3e87fc5456e7: Tablee0ce7ca1270b4541c302833574025ff0\n  table_6dbc88c5b052629e050a099e04d7be3f: Table129722fe7124ca893b45b3f11aa2797c\n  table_4a4402f5d23fa4f9df3b8bb8e3dc2d32: Table361ca453b125de0694d45757ce574ac8\n  table_8e94e6bf050f60606c5da22bcc6bb9b2: Table682bfd8f39f1d3c2f141f8d1bfaba332\n  table_170edf3aa8f832f0f36d9b9a0c549ed4: Tablea4885bc4409d5d6aeca7a333deb32f36\n  table_8320808a7934e9fa32c17c6499414fb1: Tablee8de821cfe0519477927d4aceb53aedb\n  table_ff3ba17c4964fdcaa9d663b6fb483dd3: Tabled0b3106159632181125a90621e656efe\n  table_8f9d849161a30cb7431d221283f29c43: Tablef8d58e2b9ad74400d9d3b73e1c56b24c\n  table_593cef89801d5094cdd7ad51ea3eb29c: Table7f3edc307df1ebe46a26c3cdcce01825\n  table_e021bdbeb32ee1578e7462ebf75dfb7a: Table4cb9cce2545216afbbe27fd7f598670d\n  table_2d8fef6ee4574f9180a0c7f593f47442: Table075be2c4bc1569d9e2a0f43c706845cd\n  table_cdf7f8adce5092d3805a7526a2551c2a: Tableb0475c12dae1800e6f9bed0ecc74d8ac\n  table_ea38a156b8018fa2d1034393d595c1b5: Table9273711f2c37ed469c438c6e604205ad\n  table_871b4c9fc59eb1005340453c9936c38d: Table674852753d920a7b8c85e3d7f0741d69\n  table_000a8a0cb7f265a624c851d3e7f8b946: Table93fcd1b734496b580b42aff395ed8deb\n  table_e868614c9689160521a0f7cd8fe444f9: Tabled97726553a6203a2e1fe24edf923c1bf\n  table_eb4b47c599bd30509bef47d1ea3a29e0: Table10a7b3d08bae6a280681dd4b1b4d03ea\n  my_table: MyTable\n  table_1474a7e0348b1ca363ee4a2a5dc4a1ec: Table5e096b65e80874785e32076304380404\n  table_921d1c0613d8e78089f21fdc086c6254: Tablef3ed8107e22455983dfec1061f270c5b\n  table_8f856811783bf2c6dc1cd3fafa065e91: Tablec051ae09c6cf6d7d3ea3732241b7ec9d\n  table_276c7389f255e47fa56f3db3b7b203f4: Table58d873381dd856073dc8af727f75a83c\n  table_f0e61821517de97ae60ce2db4211f6de: Table2efbbc557d528fa0179d8200f20bd375\n  table_444765b0f61d176f3e075fcd0aba7ac9: Tableb1c2cd01d00c7351140f576d84e64fc1\n  table_7a27c425067f969bf5207fe7646fd5c7: Table173d3cc6670ed190157f57b6fc5f789f\n  table_b4454c9867da1740a95d198a0309bb1c: Tableea7fc406759eeeabe58177f5dc5b2749\n  table_d7b45912e5ca97cdbb9a13ddeae017e9: Table5d31333676303c399518c2fc4cf6ce6b\n  table_ede804aecaaa0ad1a5afffb9b2a0d927: Table411a4da56c483124eeb78d27496b6bcc\n  table_18c53fd6b99123cd1d5416c633d1d257: Table90b86be76e1fe1dcbfeb23aac1268f60\n  table_3b5daebf6b386d473d143fa615a63b30: Tablead803551807f7dd640a7431281e60024\n  table_3e32e29fb3ace788a139de83f6baf360: Tableacd9c0e145638abbf38c6c9982b5d978\n  table_6b330a3b9c49a6e7867514797facf15e: Table03d5e3f6a5a1305f36b6f5e7b40f8607\n  table_0193342fd1dd6f0d57893e54a6235090: Table1ad14a94caab8e7087a497085d7136ee\n  table_c5f1901de2a3954057ebdea18ec92851: Table13e2dfe71a6146bf0f7286309cee804f\n  table_b5e6a54f6ffa9f4314e45fcf5ddfc499: Tablec227d3e74b291218da01d96ad8e3cbf3\n  table_da9bc7793b7e3784c03d55128145b7e3: Tabled861babbb2f5fa7cd7537704e5000a83\n}\n\nfunction testHugeDBSelect(db: Kysely<DB>) {\n  db.selectFrom((eb) =>\n    eb\n      .selectFrom('my_table')\n      .where((eb) => eb('my_table.id', 'in', [1, 2, 3]))\n      .selectAll()\n      .as('test'),\n  ).selectAll()\n\n  expectError(\n    db\n      .selectFrom((eb) =>\n        eb\n          .selectFrom('not_a_table')\n          .where('my_table.id', 'in', [1, 2, 3])\n          .selectAll()\n          .as('test'),\n      )\n      .selectAll(),\n  )\n}\n\nfunction testHugeDBInsert(db: Kysely<DB>) {\n  db.insertInto('my_table').defaultValues()\n\n  expectError(db.insertInto('not_a_table').defaultValues())\n}\n\nfunction testHugeDBUpdate(db: Kysely<DB>) {\n  db.updateTable('my_table').where((eb) => eb('my_table.id', 'in', [1, 2, 3]))\n  db.updateTable('my_table')\n    .from('table_000a8a0cb7f265a624c851d3e7f8b946')\n    .where((eb) => eb('my_table.id', 'in', [1, 2, 3]))\n    .set('my_table.col_164b7896ec8e770207febe0812c5f052', 1)\n\n  expectError(\n    db.updateTable('not_a_table').where('my_table.id', 'in', [1, 2, 3]),\n  )\n}\n\nfunction testHugeDBDelete(db: Kysely<DB>) {\n  db.deleteFrom('my_table').where((eb) => eb('my_table.id', 'in', [1, 2, 3]))\n\n  expectError(\n    db.deleteFrom('not_a_table').where('my_table.id', 'in', [1, 2, 3]),\n  )\n}\n"
  },
  {
    "path": "test/typings/test-d/if.test-d.ts",
    "content": "import type { Kysely, InsertResult, UpdateResult, DeleteResult } from '..'\nimport type { Database } from '../shared'\nimport { expectType } from 'tsd'\n\nasync function testIfInSelect(db: Kysely<Database>) {\n  const condition = Math.random() < 0.5\n\n  // Conditional select\n  const [r1] = await db\n    .selectFrom('pet as p')\n    .select('p.species')\n    .$if(condition, (qb) => qb.select('id'))\n    .execute()\n\n  // Conditional inner join\n  const [r2] = await db\n    .selectFrom('pet as p')\n    .select('p.species')\n    .$if(condition, (qb) => qb.innerJoin('person', 'person.id', 'p.owner_id'))\n    .execute()\n\n  expectType<{ species: 'dog' | 'cat' }>(r2)\n\n  // Conditional inner join with selection\n  const [r3] = await db\n    .selectFrom('pet as p')\n    .select('p.species')\n    .$if(condition, (qb) =>\n      qb\n        .innerJoin('person', 'person.id', 'p.owner_id')\n        .select('age as person_age'),\n    )\n    .execute()\n\n  expectType<{ species: 'dog' | 'cat'; person_age?: number }>(r3)\n\n  // Conditional left join\n  const [r4] = await db\n    .selectFrom('pet as p')\n    .select('p.species')\n    .$if(condition, (qb) => qb.leftJoin('person', 'person.id', 'p.owner_id'))\n    .execute()\n\n  expectType<{ species: 'dog' | 'cat' }>(r4)\n\n  // Conditional left join with selection\n  const [r5] = await db\n    .selectFrom('pet as p')\n    .select('p.species')\n    .$if(condition, (qb) =>\n      qb\n        .leftJoin('person', 'person.id', 'p.owner_id')\n        .select('age as person_age'),\n    )\n    .execute()\n\n  expectType<{ species: 'dog' | 'cat'; person_age?: number | null }>(r5)\n}\n\nasync function testIfInInsert(db: Kysely<Database>) {\n  const condition = Math.random() < 0.5\n\n  // Conditional returning in insert\n  const [r1] = await db\n    .insertInto('person')\n    .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 })\n    .$if(condition, (qb) => qb.returning('first_name'))\n    .execute()\n\n  expectType<{ first_name?: string }>(r1)\n\n  // Conditional additional returning in insert\n  const [r2] = await db\n    .insertInto('person')\n    .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 })\n    .returning('first_name')\n    .$if(condition, (qb) => qb.returning('last_name'))\n    .execute()\n\n  expectType<{ first_name: string; last_name?: string | null }>(r2)\n\n  // Conditional ignore in insert\n  const [r3] = await db\n    .insertInto('person')\n    .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 })\n    .$if(condition, (qb) => qb.ignore())\n    .execute()\n\n  expectType<InsertResult>(r3)\n\n  // Conditional ignore after returning in insert\n  const [r4] = await db\n    .insertInto('person')\n    .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 })\n    .returning('first_name')\n    .$if(condition, (qb) => qb.ignore())\n    .execute()\n\n  expectType<{ first_name: string }>(r4)\n}\n\nasync function testIfInUpdate(db: Kysely<Database>) {\n  const condition = Math.random() < 0.5\n\n  // Conditional returning in update\n  const [r1] = await db\n    .updateTable('person')\n    .set({ last_name: 'Foo' })\n    .$if(condition, (qb) => qb.returning('first_name'))\n    .execute()\n\n  expectType<{ first_name?: string }>(r1)\n\n  // Conditional additional returning in update\n  const [r2] = await db\n    .updateTable('person')\n    .set({ last_name: 'Foo' })\n    .returning('first_name')\n    .$if(condition, (qb) => qb.returning('last_name'))\n    .execute()\n\n  expectType<{ first_name: string; last_name?: string | null }>(r2)\n\n  // Conditional where in update\n  const [r3] = await db\n    .updateTable('person')\n    .set({ last_name: 'Foo' })\n    .$if(condition, (qb) => qb.where('id', '=', 1))\n    .execute()\n\n  expectType<UpdateResult>(r3)\n\n  // Conditional where after returning in update\n  const [r4] = await db\n    .updateTable('person')\n    .set({ last_name: 'Foo' })\n    .returning('first_name')\n    .$if(condition, (qb) => qb.where('id', '=', 1))\n    .execute()\n\n  expectType<{ first_name: string }>(r4)\n}\n\nasync function testIfInDelete(db: Kysely<Database>) {\n  const condition = Math.random() < 0.5\n\n  // Conditional returning in delete\n  const [r1] = await db\n    .deleteFrom('person')\n    .$if(condition, (qb) => qb.returning('first_name'))\n    .execute()\n\n  expectType<{ first_name?: string }>(r1)\n\n  // Conditional additional returning in delete\n  const [r2] = await db\n    .deleteFrom('person')\n    .returning('first_name')\n    .$if(condition, (qb) => qb.returning('last_name'))\n    .execute()\n\n  expectType<{ first_name: string; last_name?: string | null }>(r2)\n\n  // Conditional where in delete\n  const [r3] = await db\n    .deleteFrom('person')\n    .$if(condition, (qb) => qb.where('id', '=', 1))\n    .execute()\n\n  expectType<DeleteResult>(r3)\n\n  // Conditional where after returning in delete\n  const [r4] = await db\n    .deleteFrom('person')\n    .returning('first_name')\n    .$if(condition, (qb) => qb.where('id', '=', 1))\n    .execute()\n\n  expectType<{ first_name: string }>(r4)\n}\n"
  },
  {
    "path": "test/typings/test-d/index.test-d.ts",
    "content": "/**\n * The type tests in this file can be run using `tsd`. Even though the unit\n * and integration tests should test most of the typings as well, this file is\n * needed to test some tricky typings that, if broken, don't necessarily show\n * up in the unit or integration tests. For example if the typings are broken\n * in a way that produces `any` types, the unit and integration tests are\n * happy, but we can catch it here.\n */\n\nimport type { Kysely, Transaction, InsertResult, Selectable } from '..'\n\nimport type { Database, Person } from '../shared'\nimport { expectType, expectError } from 'tsd'\n\nasync function testOrderBy(db: Kysely<Database>) {\n  const r1 = await db\n    .selectFrom('person')\n    .select(['id', 'person.first_name as fn'])\n    .orderBy('first_name', 'desc')\n    // Should be able to reference selections.\n    .orderBy('fn')\n    .execute()\n}\n\nasync function testKyselyAndTransactionTypes(db: Kysely<Database>) {\n  let trx: Transaction<Database> = {} as unknown as Transaction<Database>\n\n  // Should not be able to assign a Kysely to a Transaction\n  expectError((trx = db))\n\n  // Should be able to assign a Transaction to Kysely\n  db = trx\n}\n\nasync function testExecuteTakeFirstOrThrow(db: Kysely<Database>) {\n  const r1 = await db\n    .selectFrom('person')\n    .selectAll()\n    .where('id', '=', 1)\n    .executeTakeFirstOrThrow()\n\n  expectType<Selectable<Person>>(r1)\n}\n\nasync function testCall(db: Kysely<Database>) {\n  // Table with alias\n  const [r1] = await db\n    .selectFrom('pet as p')\n    .select('p.species')\n    .$call((qb) => qb.select('name'))\n    .execute()\n\n  expectType<{ species: 'dog' | 'cat'; name: string }>(r1)\n}\n\nasync function testReplace(db: Kysely<Database>) {\n  const person = {\n    id: 10,\n    first_name: 'Jennifer',\n    last_name: 'Aniston',\n    gender: 'other' as const,\n    age: 30,\n  }\n\n  const r1 = await db.replaceInto('person').values(person).execute()\n\n  expectType<InsertResult[]>(r1)\n\n  const r2 = await db\n    .replaceInto('person')\n    .values({ id: 11, first_name: 'fname', age: 10, gender: 'other' })\n    .executeTakeFirst()\n\n  expectType<InsertResult>(r2)\n\n  const r3 = await db\n    .replaceInto('person')\n    .values(person)\n    .executeTakeFirstOrThrow()\n\n  expectType<InsertResult>(r3)\n\n  const r4 = await db\n    .with('foo', (db) =>\n      db.selectFrom('person').select('id').where('person.id', '=', 1),\n    )\n    .replaceInto('movie')\n    .values({\n      id: '123',\n      stars: (eb) => eb.selectFrom('foo').select('foo.id'),\n    })\n    .executeTakeFirst()\n\n  expectType<InsertResult>(r4)\n\n  // Non-existent table\n  expectError(db.replaceInto('doesnt_exists'))\n\n  // Non-existent column\n  expectError(db.replaceInto('person').values({ not_column: 'foo' }))\n\n  // Wrong type for a column\n  expectError(\n    db\n      .replaceInto('person')\n      .values({ first_name: 10, age: 10, gender: 'other' }),\n  )\n\n  // Missing required columns\n  expectError(\n    db.replaceInto('person').values({ age: 5, first_name: 'Jennifer' }),\n  )\n\n  // Explicitly excluded column\n  expectError(db.replaceInto('person').values({ modified_at: new Date() }))\n\n  // GeneratedAlways column is not allowed to be inserted/replaced\n  expectError(db.replaceInto('book').values({ id: 1, name: 'foo' }))\n\n  db.replaceInto('book').values({ name: 'bar' })\n}\n"
  },
  {
    "path": "test/typings/test-d/infer-result.test-d.ts",
    "content": "import { expectType } from 'tsd'\n\nimport type {\n  DeleteResult,\n  Equals,\n  InferResult,\n  InsertResult,\n  Kysely,\n  MergeResult,\n  Selectable,\n  UpdateResult,\n} from '..'\nimport type { Database, Person, Pet } from '../shared'\n\nfunction testInferResultSelectQuery(db: Kysely<Database>) {\n  const query0 = db.selectFrom('person').selectAll()\n  const compiledQuery0 = query0.compile()\n\n  type Expected0 = Selectable<Person>[]\n  expectType<Equals<Expected0, InferResult<typeof query0>>>(true)\n  expectType<Equals<Expected0, InferResult<typeof compiledQuery0>>>(true)\n\n  const query1 = db.selectFrom('person').select(['id', 'first_name'])\n  const compiledQuery1 = query1.compile()\n\n  type Expected1 = { id: number; first_name: string }[]\n  expectType<Equals<Expected1, InferResult<typeof query1>>>(true)\n  expectType<Equals<Expected1, InferResult<typeof compiledQuery1>>>(true)\n\n  const query2 = db\n    .selectFrom('person')\n    .innerJoin('pet', 'pet.owner_id', 'person.id')\n    .select(['person.first_name', 'pet.name'])\n  const compiledQuery2 = query2.compile()\n\n  type Expected2 = { first_name: string; name: string }[]\n  expectType<Equals<Expected2, InferResult<typeof query2>>>(true)\n  expectType<Equals<Expected2, InferResult<typeof compiledQuery2>>>(true)\n}\n\nfunction testInferResultInsertQuery(db: Kysely<Database>) {\n  const query0 = db.insertInto('person').values({\n    first_name: 'Foo',\n    last_name: 'Barson',\n    gender: 'other',\n    age: 15,\n  })\n  const compiledQuery0 = query0.compile()\n\n  type Expected0 = InsertResult[]\n  expectType<Equals<Expected0, InferResult<typeof query0>>>(true)\n  expectType<Equals<Expected0, InferResult<typeof compiledQuery0>>>(true)\n\n  const query1 = query0.returningAll()\n  const compiledQuery1 = query1.compile()\n\n  type Expected1 = Selectable<Person>[]\n  expectType<Equals<Expected1, InferResult<typeof query1>>>(true)\n  expectType<Equals<Expected1, InferResult<typeof compiledQuery1>>>(true)\n\n  const query2 = query0.returning('modified_at')\n  const compiledQuery2 = query2.compile()\n\n  type Expected2 = { modified_at: Date }[]\n  expectType<Equals<Expected2, InferResult<typeof query2>>>(true)\n  expectType<Equals<Expected2, InferResult<typeof compiledQuery2>>>(true)\n}\n\nfunction testInferResultUpdateQuery(db: Kysely<Database>) {\n  const query0 = db\n    .updateTable('person')\n    .innerJoin('pet', 'pet.owner_id', 'person.id')\n    .set({ last_name: 'Jennifer' })\n    .where('pet.id', '=', '1')\n  const compiledQuery0 = query0.compile()\n\n  type Expected0 = UpdateResult[]\n  expectType<Equals<Expected0, InferResult<typeof query0>>>(true)\n  expectType<Equals<Expected0, InferResult<typeof compiledQuery0>>>(true)\n\n  const query1 = query0.returningAll()\n  const compiledQuery1 = query1.compile()\n\n  type Expected1 = {\n    id: string | number\n    first_name: string\n    last_name: string | null\n    age: number\n    gender: 'male' | 'female' | 'other'\n    marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n    modified_at: Date\n    deleted_at: Date | null\n    name: string\n    owner_id: number\n    species: 'dog' | 'cat'\n  }[]\n\n  const expected1: Expected1 = undefined!\n  expectType<InferResult<typeof query1>>(expected1)\n  expectType<InferResult<typeof compiledQuery1>>(expected1)\n\n  const query2 = query0.returning('modified_at')\n  const compiledQuery2 = query2.compile()\n\n  type Expected2 = { modified_at: Date }[]\n  expectType<Equals<Expected2, InferResult<typeof query2>>>(true)\n  expectType<Equals<Expected2, InferResult<typeof compiledQuery2>>>(true)\n}\n\nfunction testInferResultDeleteQuery(db: Kysely<Database>) {\n  const query0 = db.deleteFrom('pet').where('id', '=', '1')\n  const compiledQuery0 = query0.compile()\n\n  type Expected0 = DeleteResult[]\n  expectType<Equals<Expected0, InferResult<typeof query0>>>(true)\n  expectType<Equals<Expected0, InferResult<typeof compiledQuery0>>>(true)\n\n  const query1 = query0.returningAll()\n  const compiledQuery1 = query1.compile()\n\n  type Expected1 = Selectable<Pet>[]\n  expectType<Equals<Expected1, InferResult<typeof query1>>>(true)\n  expectType<Equals<Expected1, InferResult<typeof compiledQuery1>>>(true)\n\n  const query2 = query0.returning('id')\n  const compiledQuery2 = query2.compile()\n\n  type Expected2 = { id: string }[]\n  expectType<Equals<Expected2, InferResult<typeof query2>>>(true)\n  expectType<Equals<Expected2, InferResult<typeof compiledQuery2>>>(true)\n}\n\nfunction testInferResultMergeQuery(db: Kysely<Database>) {\n  const query0 = db\n    .mergeInto('person')\n    .using('pet', 'pet.owner_id', 'person.id')\n    .whenMatched()\n    .thenDelete()\n  const compiledQuery0 = query0.compile()\n\n  type Expected0 = MergeResult[]\n  expectType<Equals<Expected0, InferResult<typeof query0>>>(true)\n  expectType<Equals<Expected0, InferResult<typeof compiledQuery0>>>(true)\n}\n"
  },
  {
    "path": "test/typings/test-d/insert.test-d.ts",
    "content": "import { expectError, expectType } from 'tsd'\nimport { type Insertable, type InsertResult, type Kysely, sql } from '..'\nimport type { Database } from '../shared'\n\nasync function testInsert(db: Kysely<Database>) {\n  const person = {\n    first_name: 'Jennifer',\n    last_name: 'Aniston',\n    gender: 'other' as const,\n    age: 30,\n  }\n\n  // Insert one row\n  const r1 = await db.insertInto('person').values(person).execute()\n\n  expectType<InsertResult[]>(r1)\n\n  // Should be able to leave out nullable columns like last_name\n  const r2 = await db\n    .insertInto('person')\n    .values({ first_name: 'fname', age: 10, gender: 'other' })\n    .executeTakeFirst()\n\n  expectType<InsertResult>(r2)\n\n  // The result type is correct when executeTakeFirstOrThrow is used\n  const r3 = await db\n    .insertInto('person')\n    .values(person)\n    .executeTakeFirstOrThrow()\n\n  expectType<InsertResult>(r3)\n\n  // Insert values from a CTE\n  const r4 = await db\n    .with('foo', (db) =>\n      db.selectFrom('person').select('id').where('person.id', '=', 1),\n    )\n    .insertInto('movie')\n    .values({\n      stars: (eb) => eb.selectFrom('foo').select('foo.id'),\n    })\n    .executeTakeFirst()\n\n  expectType<InsertResult>(r4)\n\n  // Insert with an on conflict statement\n  const r5 = await db\n    .insertInto('person')\n    .values(person)\n    .onConflict((oc) =>\n      oc.column('id').doUpdateSet({\n        // Should be able to reference the `excluded` \"table\"\n        first_name: (eb) => eb.ref('excluded.first_name'),\n        last_name: (eb) => eb.ref('last_name'),\n        // `excluded` \"table\" should take the `UpdateType` of complex columns.\n        deleted_at: (eb) => eb.ref('excluded.deleted_at'),\n      }),\n    )\n    .executeTakeFirst()\n\n  expectType<InsertResult>(r5)\n\n  const r6 = await db\n    .insertInto('person')\n    .values((eb) => ({\n      first_name: 'fname',\n      age: 10,\n      gender: eb.ref('gender'),\n    }))\n    .executeTakeFirst()\n\n  expectType<InsertResult>(r6)\n\n  // Non-existent table\n  expectError(db.insertInto('doesnt_exists'))\n\n  // Non-existent column\n  expectError(\n    db.insertInto('person').values({ first_name: 'Foo', not_column: 'foo' }),\n  )\n\n  // Wrong type for a column\n  expectError(\n    db\n      .insertInto('person')\n      .values({ first_name: 10, age: 10, gender: 'other' }),\n  )\n\n  // Missing required columns\n  expectError(db.insertInto('person').values({ first_name: 'Jennifer' }))\n\n  // Explicitly excluded column\n  expectError(db.insertInto('person').values({ modified_at: new Date() }))\n\n  // Non-existent column in a `doUpdateSet` call.\n  expectError(\n    db\n      .insertInto('person')\n      .values(person)\n      .onConflict((oc) =>\n        oc.column('id').doUpdateSet({\n          first_name: (eb) => eb.ref('doesnt_exist'),\n        }),\n      ),\n  )\n\n  // GeneratedAlways column is not allowed to be inserted\n  expectError(db.insertInto('book').values({ id: 1, name: 'foo' }))\n\n  // Wrong subquery return value type\n  expectError(\n    db.insertInto('person').values({\n      first_name: 'what',\n      gender: 'male',\n      age: (eb) => eb.selectFrom('pet').select('pet.name'),\n    }),\n  )\n\n  // Nullable column as undefined\n  const insertObject: {\n    first_name: string\n    last_name: string | undefined\n    age: number\n    gender: 'male' | 'female' | 'other'\n  } = {\n    first_name: 'emily',\n    last_name: 'smith',\n    age: 25,\n    gender: 'female',\n  }\n\n  db.insertInto('person').values(insertObject)\n}\n\nasync function testReturning(db: Kysely<Database>) {\n  const person = {\n    first_name: 'Jennifer',\n    last_name: 'Aniston',\n    gender: 'other' as const,\n    age: 30,\n  }\n\n  // One returning expression\n  const r1 = await db\n    .insertInto('person')\n    .values(person)\n    .returning('id')\n    .executeTakeFirst()\n\n  expectType<\n    | {\n        id: number\n      }\n    | undefined\n  >(r1)\n\n  // Multiple returning expressions\n  const r2 = await db\n    .insertInto('person')\n    .values(person)\n    .returning(['id', 'person.first_name as fn'])\n    .execute()\n\n  expectType<\n    {\n      id: number\n      fn: string\n    }[]\n  >(r2)\n\n  // Non-column reference returning expressions\n  const r3 = await db\n    .insertInto('person')\n    .values(person)\n    .returning([\n      'id',\n      sql<string>`concat(first_name, ' ', last_name)`.as('full_name'),\n      (qb) => qb.selectFrom('pet').select('pet.id').as('sub'),\n    ])\n    .execute()\n\n  expectType<\n    {\n      id: number\n      full_name: string\n      sub: string | null\n    }[]\n  >(r3)\n\n  const r4 = await db\n    .insertInto('movie')\n    .values({ stars: 5 })\n    .returningAll()\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    id: string\n    stars: number\n  }>(r4)\n\n  // Non-existent column\n  expectError(db.insertInto('person').values(person).returning('not_column'))\n}\n\nasync function testOutput(db: Kysely<Database>) {\n  const person = {\n    first_name: 'Jennifer',\n    last_name: 'Aniston',\n    gender: 'other' as const,\n    age: 30,\n  }\n\n  // One returning expression\n  const r1 = await db\n    .insertInto('person')\n    .output('inserted.id')\n    .values(person)\n    .executeTakeFirst()\n\n  expectType<{ id: number } | undefined>(r1)\n\n  // Multiple returning expressions\n  const r2 = await db\n    .insertInto('person')\n    .output(['inserted.id', 'inserted.first_name as fn'])\n    .values(person)\n    .execute()\n\n  expectType<{ id: number; fn: string }[]>(r2)\n\n  // Non-column reference returning expressions\n  const r3 = await db\n    .insertInto('person')\n    .output([\n      'inserted.id',\n      sql<string>`concat(inserted.first_name, ' ', inserted.last_name)`.as(\n        'full_name',\n      ),\n    ])\n    .values(person)\n    .execute()\n\n  expectType<{ id: number; full_name: string }[]>(r3)\n\n  const r4 = await db\n    .insertInto('movie')\n    .outputAll('inserted')\n    .values({ stars: 5 })\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: string; stars: number }>(r4)\n\n  // Non-existent column\n  expectError(\n    db.insertInto('person').output('inserted.not_column').values(person),\n  )\n\n  // Without prefix\n  expectError(db.insertInto('person').output('age').values(person))\n  expectError(db.insertInto('person').outputAll().values(person))\n\n  // Non-existent prefix\n  expectError(db.insertInto('person').output('foo.age').values(person))\n  expectError(db.insertInto('person').outputAll('foo').values(person))\n\n  // Wrong prefix\n  expectError(db.insertInto('person').output('deleted.age').values(person))\n  expectError(db.insertInto('person').outputAll('deleted').values(person))\n}\n\nfunction testInsertable() {\n  function foo(\n    _bar: Insertable<// no required columns!\n    {\n      optional: number | null\n    }>,\n  ) {}\n\n  foo({})\n  foo({ optional: 3 })\n  foo({ optional: null })\n\n  // bad column values.\n  expectError(foo({ optional: '' }))\n  expectError(foo({ optional: Symbol.for('thing') }))\n\n  // non-object as argument.\n  expectError(foo(3))\n  expectError(foo(Symbol.for('thing')))\n}\n"
  },
  {
    "path": "test/typings/test-d/join.test-d.ts",
    "content": "import type { Kysely, Selectable } from '..'\nimport type { Database, Pet } from '../shared'\nimport { expectType, expectError } from 'tsd'\n\nasync function testJoin(db: Kysely<Database>) {\n  // Simple join with two columns\n  const r1 = await db\n    .selectFrom('person')\n    .innerJoin('pet', 'pet.owner_id', 'person.id')\n    .selectAll()\n    .execute()\n\n  expectType<\n    {\n      // Person columns\n      id: number | string\n      first_name: string\n      last_name: string | null\n      age: number\n      gender: 'male' | 'female' | 'other'\n      modified_at: Date\n      marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n      deleted_at: Date | null\n\n      // Pet columns.\n      name: string\n      species: 'cat' | 'dog'\n      owner_id: number\n    }[]\n  >(r1)\n\n  // Join with an alias using the join builder instead of two columns\n  const r2 = await db\n    .selectFrom('person')\n    .innerJoin('pet as p', (join) => join.onRef('p.owner_id', '=', 'person.id'))\n    .where('p.species', 'in', ['cat'])\n    .selectAll('p')\n    .execute()\n\n  expectType<Selectable<Pet>[]>(r2)\n  expectType<\n    { id: string; name: string; species: 'cat' | 'dog'; owner_id: number }[]\n  >(r2)\n\n  // Join subquery\n  const r3 = await db\n    .selectFrom('person')\n    .innerJoin(\n      db.selectFrom('pet').select(['pet.id', 'pet.owner_id as owner']).as('p'),\n      'p.owner',\n      'person.id',\n    )\n    .where('p.owner', '>', 2)\n    .selectAll('p')\n    .execute()\n\n  expectType<{ id: string; owner: number }[]>(r3)\n\n  // Join subquery using join builder\n  const r4 = await db\n    .selectFrom('person')\n    .innerJoin(\n      (qb) => qb.selectFrom('pet').selectAll('pet').as('p'),\n      (join) => join.onRef('p.owner_id', '=', 'person.id'),\n    )\n    .where('p.owner_id', '>', 2)\n    .selectAll('p')\n    .execute()\n\n  expectType<Selectable<Pet>[]>(r4)\n\n  // Two left joins\n  const r5 = await db\n    .selectFrom('person')\n    .leftJoin('pet', 'pet.owner_id', 'person.id')\n    .leftJoin('movie', 'movie.id', 'person.id')\n    .selectAll()\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    id: number | string | null\n    first_name: string\n    last_name: string | null\n    age: number\n    gender: 'male' | 'female' | 'other'\n    modified_at: Date\n    marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n    deleted_at: Date | null\n\n    // All Pet columns should be nullable because of the left join\n    name: string | null\n    species: 'dog' | 'cat' | null\n    owner_id: number | null\n\n    // All Movie columns should be nullable because of the left join\n    stars: number | null\n  }>(r5)\n\n  // Two right joins\n  const r6 = await db\n    .selectFrom('person')\n    .rightJoin('pet', 'pet.owner_id', 'person.id')\n    .rightJoin('movie', 'movie.id', 'person.id')\n    .selectAll()\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    // All Person columns should be nullable because of the right join.\n    id: number | string | null\n    first_name: string | null\n    last_name: string | null\n    age: number | null\n    gender: 'male' | 'female' | 'other' | null\n    modified_at: Date | null\n    marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n    deleted_at: Date | null\n\n    // All Pet columns should also be nullable because there's another\n    // right join after the Pet join.\n    name: string | null\n    species: 'dog' | 'cat' | null\n    owner_id: number | null\n\n    // Movie columns should not be nullable because it's the last\n    // right joined table.\n    stars: number\n  }>(r6)\n\n  // Two full joins.\n  const r7 = await db\n    .selectFrom('person')\n    .fullJoin('pet', 'pet.owner_id', 'person.id')\n    .fullJoin('movie', 'movie.id', 'person.id')\n    .selectAll()\n    .executeTakeFirstOrThrow()\n\n  // All columns should be nullable because of the full join\n  expectType<{\n    id: number | string | null\n    first_name: string | null\n    last_name: string | null\n    age: number | null\n    gender: 'male' | 'female' | 'other' | null\n    modified_at: Date | null\n    marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n    deleted_at: Date | null\n\n    name: string | null\n    species: 'dog' | 'cat' | null\n    owner_id: number | null\n\n    stars: number | null\n  }>(r7)\n\n  // Update query with a join\n  const r8 = await db\n    .updateTable('person')\n    .innerJoin('pet', 'pet.owner_id', 'person.id')\n    .set({ last_name: 'Jennifer' })\n    .where('pet.id', '=', '1')\n    .execute()\n\n  const r9 = await db\n    .selectFrom('person')\n    .innerJoinLateral(\n      (eb) =>\n        eb\n          .selectFrom('pet')\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .select('pet.name')\n          .as('pets'),\n      (jb) => jb.onTrue(),\n    )\n    .select(['person.first_name', 'pets.name'])\n    .execute()\n\n  expectType<\n    {\n      first_name: string\n      name: string\n    }[]\n  >(r9)\n\n  const r10 = await db\n    .selectFrom('person')\n    .leftJoinLateral(\n      (eb) =>\n        eb\n          .selectFrom('pet')\n          .whereRef('pet.owner_id', '=', 'person.id')\n          .select('pet.name')\n          .as('pets'),\n      (jb) => jb.onTrue(),\n    )\n    .select(['person.first_name', 'pets.name'])\n    .execute()\n\n  expectType<\n    {\n      first_name: string\n      name: string | null\n    }[]\n  >(r10)\n\n  const r11 = await db\n    .selectFrom('person')\n    .crossApply((eb) =>\n      eb\n        .selectFrom('pet')\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .select('pet.name')\n        .as('pets'),\n    )\n    .select(['person.first_name', 'pets.name'])\n    .execute()\n\n  expectType<\n    {\n      first_name: string\n      name: string\n    }[]\n  >(r11)\n\n  const r12 = await db\n    .selectFrom('person')\n    .outerApply((eb) =>\n      eb\n        .selectFrom('pet')\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .select('pet.name')\n        .as('pets'),\n    )\n    .select(['person.first_name', 'pets.name'])\n    .execute()\n\n  expectType<\n    {\n      first_name: string\n      name: string | null\n    }[]\n  >(r12)\n\n  // Refer to table that's not joined\n  expectError(\n    db.selectFrom('person').innerJoin('movie', 'movie.id', 'pet.owner_id'),\n  )\n\n  // Refer to column that doesn't exist\n  expectError(db.selectFrom('person').innerJoin('movie', 'foo', 'person.id'))\n\n  // Refer to table that's not joined\n  expectError(\n    db\n      .selectFrom('person')\n      .innerJoin('movie as m', (join) =>\n        join.onRef('pet.id', '=', 'person.id'),\n      ),\n  )\n\n  // Refer to table with wrong alias\n  expectError(\n    db\n      .selectFrom('person')\n      .innerJoin('movie as m', (join) =>\n        join.onRef('movie.id', '=', 'person.id'),\n      ),\n  )\n}\n\nasync function testManyJoins(db: Kysely<Database>) {\n  // Make sure things still work if we add a huge amount of joins.\n  const r1 = await db\n    .selectFrom('person')\n    .innerJoin('pet as p1', 'p1.owner_id', 'person.id')\n    .innerJoin('pet as p2', 'p2.owner_id', 'person.id')\n    .innerJoin('pet as p3', 'p3.owner_id', 'person.id')\n    .innerJoin('pet as p4', 'p4.owner_id', 'person.id')\n    .innerJoin('pet as p5', 'p5.owner_id', 'person.id')\n    .innerJoin('pet as p6', 'p6.owner_id', 'person.id')\n    .innerJoin('pet as p7', 'p7.owner_id', 'person.id')\n    .innerJoin('pet as p8', 'p8.owner_id', 'person.id')\n    .innerJoin('pet as p9', 'p9.owner_id', 'person.id')\n    .innerJoin('pet as p10', 'p10.owner_id', 'person.id')\n    .innerJoin('pet as p11', 'p11.owner_id', 'person.id')\n    .innerJoin('pet as p12', 'p12.owner_id', 'person.id')\n    .innerJoin('pet as p13', 'p13.owner_id', 'person.id')\n    .innerJoin('pet as p14', 'p14.owner_id', 'person.id')\n    .innerJoin('pet as p15', 'p15.owner_id', 'person.id')\n    .innerJoin('pet as p16', 'p16.owner_id', 'person.id')\n    .innerJoin('pet as p17', 'p17.owner_id', 'person.id')\n    .innerJoin('pet as p18', 'p18.owner_id', 'person.id')\n    .innerJoin('pet as p19', 'p19.owner_id', 'person.id')\n    .innerJoin('pet as p20', 'p20.owner_id', 'person.id')\n    .select(['age', 'last_name'])\n    .executeTakeFirstOrThrow()\n\n  expectType<{ age: number; last_name: string | null }>(r1)\n\n  const r2 = await db\n    .selectFrom('person')\n    .rightJoin('pet as p1', 'p1.owner_id', 'person.id')\n    .rightJoin('pet as p2', 'p2.owner_id', 'person.id')\n    .rightJoin('pet as p3', 'p3.owner_id', 'person.id')\n    .rightJoin('pet as p4', 'p4.owner_id', 'person.id')\n    .rightJoin('pet as p5', 'p5.owner_id', 'person.id')\n    .rightJoin('pet as p6', 'p6.owner_id', 'person.id')\n    .rightJoin('pet as p7', 'p7.owner_id', 'person.id')\n    .rightJoin('pet as p8', 'p8.owner_id', 'person.id')\n    .rightJoin('pet as p9', 'p9.owner_id', 'person.id')\n    .rightJoin('pet as p10', 'p10.owner_id', 'person.id')\n    .rightJoin('pet as p11', 'p11.owner_id', 'person.id')\n    .rightJoin('pet as p13', 'p13.owner_id', 'person.id')\n    .rightJoin('pet as p14', 'p14.owner_id', 'person.id')\n    .rightJoin('pet as p15', 'p15.owner_id', 'person.id')\n    .rightJoin('pet as p16', 'p16.owner_id', 'person.id')\n    .rightJoin('pet as p17', 'p17.owner_id', 'person.id')\n    .rightJoin('pet as p18', 'p18.owner_id', 'person.id')\n    .rightJoin('pet as p19', 'p19.owner_id', 'person.id')\n    .rightJoin('pet as p20', 'p20.owner_id', 'person.id')\n    .select(['age', 'last_name'])\n    .executeTakeFirstOrThrow()\n\n  expectType<{ age: number | null; last_name: string | null }>(r2)\n\n  const r3 = await db\n    .selectFrom('person')\n    .leftJoin('pet as p1', (join) =>\n      join.onRef('p1.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p2', (join) =>\n      join.onRef('p2.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p3', (join) =>\n      join.onRef('p3.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p4', (join) =>\n      join.onRef('p4.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p5', (join) =>\n      join.onRef('p5.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p6', (join) =>\n      join.onRef('p6.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p7', (join) =>\n      join.onRef('p7.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p8', (join) =>\n      join.onRef('p8.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p9', (join) =>\n      join.onRef('p9.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p10', (join) =>\n      join.onRef('p10.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p11', (join) =>\n      join.onRef('p11.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p12', (join) =>\n      join.onRef('p12.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p13', (join) =>\n      join.onRef('p13.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p14', (join) =>\n      join.onRef('p14.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p15', (join) =>\n      join.onRef('p15.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p16', (join) =>\n      join.onRef('p16.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p17', (join) =>\n      join.onRef('p17.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p18', (join) =>\n      join.onRef('p18.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p19', (join) =>\n      join.onRef('p19.owner_id', '=', 'person.id'),\n    )\n    .leftJoin('pet as p20', (join) =>\n      join.onRef('p20.owner_id', '=', 'person.id'),\n    )\n    .select(['age', 'last_name'])\n    .executeTakeFirstOrThrow()\n\n  expectType<{ age: number; last_name: string | null }>(r3)\n}\n"
  },
  {
    "path": "test/typings/test-d/json-traversal.test-d.ts",
    "content": "import { expectError, expectType } from 'tsd'\nimport type { ExpressionBuilder, JSONPathBuilder, Kysely } from '..'\nimport type { Database, PersonMetadata } from '../shared'\nimport type { KyselyTypeError } from '../../../dist/cjs/util/type-error'\n\nasync function testJSONReference(db: Kysely<Database>) {\n  const [r1] = await db\n    .selectFrom('person_metadata')\n    .select((eb) => eb.ref('website', '->>$').key('url').as('website_url'))\n    .execute()\n\n  expectType<{ website_url: string }>(r1)\n\n  const [r2] = await db\n    .selectFrom('person_metadata')\n    .select((eb) => eb.ref('nicknames', '->>$').at(0).as('nickname'))\n    .execute()\n\n  expectType<{ nickname: string | null }>(r2)\n\n  const [r3] = await db\n    .selectFrom('person_metadata')\n    .select((eb) =>\n      eb.ref('profile', '->>$').key('auth').key('roles').as('roles'),\n    )\n    .execute()\n\n  expectType<{ roles: string[] }>(r3)\n\n  const [r4] = await db\n    .selectFrom('person_metadata')\n    .select((eb) => eb.ref('profile', '->>$').key('tags').at(0).as('main_tag'))\n    .execute()\n\n  expectType<{ main_tag: string | null }>(r4)\n\n  const [r5] = await db\n    .selectFrom('person_metadata')\n    .select((eb) =>\n      eb\n        .ref('experience', '->>$')\n        .at(0)\n        .key('establishment')\n        .as('establishment'),\n    )\n    .execute()\n\n  expectType<{ establishment: string | null }>(r5)\n\n  const [r6] = await db\n    .selectFrom('person_metadata')\n    .select((eb) =>\n      eb.ref('schedule', '->>$').at(0).at(0).as('january_1st_schedule'),\n    )\n    .execute()\n\n  expectType<{ january_1st_schedule: { name: string; time: string }[] | null }>(\n    r6,\n  )\n\n  const [r7] = await db\n    .selectFrom('person_metadata')\n    .select((eb) => eb.ref('nicknames', '->>$').at('last').as('nickname'))\n    .execute()\n\n  expectType<{ nickname: string | null }>(r7)\n\n  const [r8] = await db\n    .selectFrom('person_metadata')\n    .select((eb) => eb.ref('nicknames', '->>$').at('#-1').as('nickname'))\n    .execute()\n\n  expectType<{ nickname: string | null }>(r8)\n\n  const [r9] = await db\n    .selectFrom('person_metadata')\n    .select((eb) => eb.ref('record', '->').key('i_dunno_man').as('whatever'))\n    .execute()\n\n  expectType<{ whatever: string | null }>(r9)\n\n  const [r10] = await db\n    .selectFrom('person_metadata')\n    .select((eb) => eb.ref('array', '->').at(0).as('whenever'))\n    .execute()\n\n  expectType<{ whenever: string | null }>(r10)\n\n  // `.$castTo()` should support chaining with `.as(...)` #1139\n  const [r11] = await db\n    .selectFrom('person_metadata')\n    .select((eb) =>\n      eb\n        .ref('array', '->')\n        .at(0)\n        .$castTo<(string & { _brand: 'whenever' }) | null>()\n        .as('whenever'),\n    )\n    .execute()\n\n  expectType<{ whenever: (string & { _brand: 'whenever' }) | null }>(r11)\n\n  // `.$notNull()` should support chaining with `.as(...)` #1139\n  const [r12] = await db\n    .selectFrom('person_metadata')\n    .select((eb) => eb.ref('array', '->').at(0).$notNull().as('whenever'))\n    .execute()\n\n  expectType<{ whenever: string }>(r12)\n\n  // missing operator\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('experience').at(0).as('alias')),\n  )\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('website').key('url').as('alias')),\n  )\n\n  // invalid operator\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) =>\n        eb.ref('website', 'NO_SUCH_OPERATOR').key('url').as('alias'),\n      )\n      .execute(),\n  )\n\n  // use `key` on non-object\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('nicknames', '->>$').key('url').as('alias'))\n      .execute(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => [\n        eb.ref('website', '->>').key('url').key('length').as('alias'),\n        eb.ref('schedule', '->>').key('length').as('alias2'),\n      ])\n      .execute(),\n  )\n\n  // use `at` on non-array\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('website', '->>$').at(0).as('alias'))\n      .execute(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('experience', '->>').at(0).at(-1).as('alias'))\n      .execute(),\n  )\n\n  // bad key\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) =>\n        eb.ref('website', '->>$').key('NO_SUCH_FIELD').as('alias'),\n      )\n      .execute(),\n  )\n\n  // bad index\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('nicknames', '->>$').at('0').as('alias'))\n      .execute(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('nicknames', '->>$').at(0.5).as('alias'))\n      .execute(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('nicknames', '->>$').at('#--1').as('alias'))\n      .execute(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('nicknames', '->>$').at('#-1.5').as('alias'))\n      .execute(),\n  )\n\n  expectError(\n    db\n      .selectFrom('person_metadata')\n      .select((eb) => eb.ref('nicknames', '->>$').at('last ').as('alias'))\n      .execute(),\n  )\n}\n\nasync function testJSONPath(eb: ExpressionBuilder<Database, keyof Database>) {\n  expectType<JSONPathBuilder<PersonMetadata['experience']>>(\n    eb.jsonPath<'experience'>(),\n  )\n\n  expectType<JSONPathBuilder<PersonMetadata['experience']>>(\n    eb.jsonPath<'person_metadata.experience'>(),\n  )\n\n  expectError(eb.jsonPath('experience'))\n  expectError(eb.jsonPath('person_metadata.experience'))\n  expectType<\n    KyselyTypeError<\"You must provide a column reference as this method's $ generic\">\n  >(eb.jsonPath())\n  expectError(eb.jsonPath<'NO_SUCH_COLUMN'>())\n}\n"
  },
  {
    "path": "test/typings/test-d/kysely-any.test-d.ts",
    "content": "import type { DeleteResult, InsertResult, Kysely, UpdateResult } from '..'\nimport { expectType } from 'tsd'\n\nasync function testKyselyAnySelects(db: Kysely<any>) {\n  const r1 = await db.selectFrom('foo').select('bar').execute()\n  expectType<{ bar: any }[]>(r1)\n\n  const r2 = await db.selectFrom('foo').select(['bar', 'baz']).execute()\n  expectType<{ bar: any; baz: any }[]>(r2)\n\n  const r3 = await db.selectFrom('foo').select('foo.bar').execute()\n  expectType<{ bar: any }[]>(r3)\n\n  const r4 = await db\n    .selectFrom('foo')\n    .select(['spam', 'foo.bar', 'foo.baz'])\n    .execute()\n  expectType<{ spam: any; bar: any; baz: any }[]>(r4)\n\n  const r5 = await db\n    .selectFrom(['foo1', 'foo2'])\n    .select(['spam', 'foo1.bar', 'foo2.baz', 'doesnotexists.fux'])\n    .execute()\n  expectType<{ spam: any; bar: any; baz: any; fux: any }[]>(r5)\n\n  const r6 = await db\n    .selectFrom('foo')\n    .select((eb) => [\n      eb.lit(1).as('baz'),\n      eb.ref('foo.bar').as('bar'),\n      eb\n        .selectFrom('bar')\n        .select('spam')\n        .whereRef('foo.id', '=', 'bar.id')\n        .as('spam'),\n    ])\n    .executeTakeFirstOrThrow()\n  expectType<{ bar: any; spam: any; baz: 1 }>(r6)\n\n  const table: 'foo' | 'bar' = Math.random() > 0.5 ? 'foo' : 'bar'\n  const r7 = await db.selectFrom(table).select('baz').executeTakeFirstOrThrow()\n  expectType<{ baz: any }>(r7)\n\n  const r8 = await db.selectFrom('foo as f').select('bar').execute()\n  expectType<{ bar: any }[]>(r8)\n\n  const r9 = await db\n    .selectFrom(['foo1 as f1', 'foo2 as f2'])\n    .select(['spam', 'f1.bar', 'f2.baz', 'doesnotexists.fux'])\n    .execute()\n  expectType<{ spam: any; bar: any; baz: any; fux: any }[]>(r9)\n}\n\nasync function testKyselyAnyInserts(db: Kysely<any>) {\n  const r1 = await db\n    .insertInto('foo')\n    .values({ bar: 'baz', spam: 1 })\n    .executeTakeFirstOrThrow()\n  expectType<InsertResult>(r1)\n\n  const r2 = await db\n    .insertInto('foo')\n    .values({ bar: 'baz', spam: 1 })\n    .returning('foo')\n    .executeTakeFirstOrThrow()\n  expectType<{ foo: any }>(r2)\n\n  const r3 = await db\n    .insertInto('foo')\n    .values({ bar: 'baz', spam: 1 })\n    .returning(['foo', 'baz'])\n    .executeTakeFirstOrThrow()\n  expectType<{ foo: any; baz: any }>(r3)\n\n  const r4 = await db\n    .insertInto('foo')\n    .values((eb) => ({ foo: eb.ref('foo.bar') }))\n    .executeTakeFirstOrThrow()\n  expectType<InsertResult>(r4)\n\n  const table: 'foo' | 'bar' = Math.random() > 0.5 ? 'foo' : 'bar'\n  const r5 = await db\n    .insertInto(table)\n    .values((eb) => ({ foo: eb.ref('foo.bar') }))\n    .executeTakeFirstOrThrow()\n  expectType<InsertResult>(r5)\n}\n\nasync function testKyselyAnyUpdates(db: Kysely<any>) {\n  const r1 = await db\n    .updateTable('foo')\n    .set({ bar: 'baz', spam: 1 })\n    .where('foo.eggs', '=', 1)\n    .executeTakeFirstOrThrow()\n  expectType<UpdateResult>(r1)\n\n  const r2 = await db\n    .updateTable('foo as f')\n    .set({ bar: 'baz', spam: 1 })\n    .where('f.eggs', '=', 1)\n    .where('spam', '=', 2)\n    .executeTakeFirstOrThrow()\n  expectType<UpdateResult>(r2)\n\n  const r3 = await db\n    .updateTable('foo')\n    .set({ bar: 'baz', spam: 1 })\n    .where('foo.eggs', '=', 1)\n    .where('spam', '=', 2)\n    .returning(['a', 'b'])\n    .executeTakeFirstOrThrow()\n  expectType<{ a: any; b: any }>(r3)\n\n  const r4 = await db\n    .updateTable('foo')\n    .set((eb) => ({\n      foo: eb('foo.bar', '=', 1),\n    }))\n    .where('foo.eggs', '=', 1)\n    .executeTakeFirstOrThrow()\n  expectType<UpdateResult>(r4)\n\n  const table: 'foo' | 'bar' = Math.random() > 0.5 ? 'foo' : 'bar'\n  const r5 = await db\n    .updateTable(table)\n    .set((eb) => ({\n      foo: eb('foo.bar', '=', 1),\n    }))\n    .where('foo.eggs', '=', 1)\n    .executeTakeFirstOrThrow()\n  expectType<UpdateResult>(r5)\n}\n\nasync function testKyselyAnyDeletes(db: Kysely<any>) {\n  const r1 = await db\n    .deleteFrom('foo')\n    .where('foo.eggs', '=', 1)\n    .where('spam', '=', 2)\n    .executeTakeFirstOrThrow()\n  expectType<DeleteResult>(r1)\n\n  const r2 = await db\n    .deleteFrom('foo as f')\n    .where('f.eggs', '=', 1)\n    .where('spam', '=', 2)\n    .executeTakeFirstOrThrow()\n  expectType<DeleteResult>(r2)\n\n  const r3 = await db\n    .deleteFrom('foo')\n    .where('foo.eggs', '=', 1)\n    .where('spam', '=', 2)\n    .returning(['a', 'b'])\n    .executeTakeFirstOrThrow()\n  expectType<{ a: any; b: any }>(r3)\n\n  const table: 'foo' | 'bar' = Math.random() > 0.5 ? 'foo' : 'bar'\n  const r4 = await db\n    .deleteFrom(table)\n    .where('baz', '=', 1)\n    .executeTakeFirstOrThrow()\n  expectType<DeleteResult>(r4)\n}\n"
  },
  {
    "path": "test/typings/test-d/merge.test-d.ts",
    "content": "import { expectError, expectType } from 'tsd'\nimport {\n  type ExpressionBuilder,\n  type JoinBuilder,\n  type Kysely,\n  type MatchedThenableMergeQueryBuilder,\n  type MergeQueryBuilder,\n  type MergeResult,\n  type NotMatchedThenableMergeQueryBuilder,\n  type SelectType,\n  type Selectable,\n  type UpdateQueryBuilder,\n  type WheneableMergeQueryBuilder,\n  mergeAction,\n  sql,\n} from '..'\nimport type { Database, Person, Pet } from '../shared'\n\nasync function testMergeInto(db: Kysely<Database>) {\n  db.mergeInto('person')\n  db.mergeInto('person as p')\n  expectError(db.mergeInto('NO_SUCH_TABLE'))\n  expectError(db.mergeInto('NO_SUCH_TABLE as n'))\n  expectError(db.mergeInto(['person']))\n  expectError(db.mergeInto(['person as p']))\n  expectError(db.mergeInto(db.selectFrom('person').selectAll().as('person')))\n  expectError(\n    db.mergeInto((eb: ExpressionBuilder<Database, keyof Database>) =>\n      eb.selectFrom('person').selectAll().as('person'),\n    ),\n  )\n\n  expectType<MergeQueryBuilder<Database, 'person', MergeResult>>(\n    db.mergeInto('person'),\n  )\n}\n\nasync function testUsing(db: Kysely<Database>) {\n  db.mergeInto('person').using('pet', 'pet.owner_id', 'person.id')\n  db.mergeInto('person as p').using('pet as p2', 'p2.owner_id', 'p.id')\n  expectError(db.mergeInto('person').using('pet'))\n  expectError(db.mergeInto('person').using('pet', 'pet'))\n  expectError(db.mergeInto('person').using('pet', 'pet.NO_SUCH_COLUMN'))\n  expectError(db.mergeInto('person').using('pet', 'pet.owner_id', 'person'))\n  expectError(\n    db\n      .mergeInto('person')\n      .using('pet', 'pet.owner_id', 'person.NO_SUCH_COLUMN'),\n  )\n  expectError(\n    db\n      .mergeInto('person')\n      .using('NO_SUCH_TABLE as n', 'n.owner_id', 'person.id'),\n  )\n  db.mergeInto('person').using('pet', (join) => {\n    // already tested in join.test-d.ts\n    expectType<JoinBuilder<Database, 'person' | 'pet'>>(join)\n\n    return join.onTrue()\n  })\n\n  expectType<\n    WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>\n  >(db.mergeInto('person').using('pet', 'pet.owner_id', 'person.id'))\n\n  expectType<MergeResult>(\n    await db\n      .mergeInto('person')\n      .using('pet', 'pet.owner_id', 'person.id')\n      .executeTakeFirstOrThrow(),\n  )\n}\n\nasync function testWhenMatched(\n  baseQuery: WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>,\n) {\n  baseQuery.whenMatched()\n  expectError(baseQuery.whenMatched('age'))\n  expectError(baseQuery.whenMatchedAnd('age'))\n  expectError(baseQuery.whenMatchedAnd('NO_SUCH_COLUMN'))\n  expectError(baseQuery.whenMatchedAnd('age', '>'))\n  expectError(baseQuery.whenMatchedAnd('age', '>', 'string'))\n  baseQuery.whenMatchedAnd('age', '>', 2)\n  expectError(baseQuery.whenMatchedAnd('age', 'NO_SUCH_OPERATOR', 2))\n  baseQuery.whenMatchedAnd('person.age', sql`>`, 2)\n  baseQuery.whenMatchedAnd('pet.species', '>', 'cat')\n  baseQuery.whenMatchedAnd('age', '>', (eb) => {\n    expectType<ExpressionBuilder<Database, 'person' | 'pet'>>(eb)\n    return eb.ref('person.age')\n  })\n  expectError(\n    baseQuery.whenMatchedAnd('age', '>', (eb) => eb.ref('person.first_name')),\n  )\n  baseQuery.whenMatchedAnd((eb) => {\n    // already tested in many places\n    expectType<ExpressionBuilder<Database, 'person' | 'pet'>>(eb)\n    return eb.and([])\n  })\n  expectError(baseQuery.whenMatchedAndRef('age'))\n  expectError(baseQuery.whenMatchedAndRef('NO_SUCH_COLUMN'))\n  expectError(baseQuery.whenMatchedAndRef('age', '>'))\n  expectError(baseQuery.whenMatchedAndRef('age', '>', 'string'))\n  expectError(baseQuery.whenMatchedAndRef('age', '>', 2))\n  baseQuery.whenMatchedAndRef('pet.name', '>', 'person.age')\n  baseQuery.whenMatchedAndRef('person.age', '>', 'pet.name')\n  baseQuery.whenMatchedAndRef('age', '>', sql`person.age`)\n  baseQuery.whenMatchedAndRef('age', sql`>`, 'person.age')\n  expectError(baseQuery.whenMatchedAndRef('age', 'NO_SUCH_OPERATOR', 'age'))\n\n  type ExpectedReturnType = MatchedThenableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    'person' | 'pet',\n    MergeResult\n  >\n  expectType<ExpectedReturnType>(baseQuery.whenMatched())\n  expectType<ExpectedReturnType>(baseQuery.whenMatchedAnd('age', '>', 2))\n  expectType<ExpectedReturnType>(\n    baseQuery.whenMatchedAndRef('pet.name', '>', 'person.age'),\n  )\n}\n\nasync function testWhenNotMatched(\n  baseQuery: WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>,\n) {\n  baseQuery.whenNotMatched()\n  expectError(baseQuery.whenNotMatched('species'))\n  expectError(baseQuery.whenNotMatchedAnd('species'))\n  expectError(baseQuery.whenNotMatchedAnd('NO_SUCH_COLUMN'))\n  expectError(baseQuery.whenNotMatchedAnd('species', '>'))\n  expectError(baseQuery.whenNotMatchedAnd('species', '>', 'string'))\n  expectError(baseQuery.whenNotMatchedAnd('species', '>', 2))\n  baseQuery.whenNotMatchedAnd('species', '>', 'dog')\n  expectError(\n    baseQuery.whenNotMatchedAnd('species', 'NOT_SUCH_OPERATOR', 'dog'),\n  )\n  // when not matched can only reference the source table's columns.\n  expectError(baseQuery.whenNotMatchedAnd('age', '>', 'dog'))\n  baseQuery.whenNotMatchedAnd('species', sql`>`, 'dog')\n  baseQuery.whenNotMatchedAnd('pet.species', '>', sql<'dog'>`dog`)\n  baseQuery.whenNotMatchedAnd('species', '>', (eb) => {\n    // already tested in many places\n    expectType<ExpressionBuilder<Database, 'pet'>>(eb)\n    return eb.ref('pet.species')\n  })\n  expectError(\n    baseQuery.whenNotMatchedAnd('species', '>', (eb) => eb.ref('pet.owner_id')),\n  )\n  baseQuery.whenNotMatchedAnd((eb) => {\n    // already tested in many places\n    expectType<ExpressionBuilder<Database, 'pet'>>(eb)\n    return eb.and([])\n  })\n  expectError(baseQuery.whenNotMatchedAndRef('species'))\n  expectError(baseQuery.whenNotMatchedAndRef('NO_SUCH_COLUMN'))\n  expectError(baseQuery.whenNotMatchedAndRef('species', '>'))\n  expectError(baseQuery.whenNotMatchedAndRef('species', '>', 'string'))\n  expectError(baseQuery.whenNotMatchedAndRef('species', '>', 2))\n  baseQuery.whenNotMatchedAndRef('pet.name', '>', 'pet.species')\n  // when not matched can only reference the source table's columns.\n  expectError(\n    baseQuery.whenNotMatchedAndRef('pet.name', '>', 'person.first_name'),\n  )\n  expectError(\n    baseQuery.whenNotMatchedAndRef('person.first_name', '>', 'pet.species'),\n  )\n  baseQuery.whenNotMatchedAndRef('species', '>', sql`person.age`)\n  baseQuery.whenNotMatchedAndRef('species', sql`>`, 'pet.species')\n  expectError(\n    baseQuery.whenNotMatchedAndRef('species', 'NO_SUCH_OPERATOR', 'name'),\n  )\n\n  type ExpectedReturnType = NotMatchedThenableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    MergeResult\n  >\n  expectType<ExpectedReturnType>(baseQuery.whenNotMatched())\n  expectType<ExpectedReturnType>(\n    baseQuery.whenNotMatchedAnd('species', '>', 'dog'),\n  )\n  expectType<ExpectedReturnType>(\n    baseQuery.whenNotMatchedAndRef('pet.name', '>', 'pet.species'),\n  )\n}\n\nasync function testWhenNotMatchedBySource(\n  baseQuery: WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>,\n) {\n  baseQuery.whenNotMatchedBySource()\n  expectError(baseQuery.whenNotMatchedBySource('age'))\n  expectError(baseQuery.whenNotMatchedBySourceAnd('age'))\n  expectError(baseQuery.whenNotMatchedBySourceAnd('NO_SUCH_COLUMN'))\n  expectError(baseQuery.whenNotMatchedBySourceAnd('age', '>'))\n  expectError(baseQuery.whenNotMatchedBySourceAnd('age', '>', 'string'))\n  baseQuery.whenNotMatchedBySourceAnd('age', '>', 2)\n  expectError(\n    baseQuery.whenNotMatchedBySourceAnd('age', 'NOT_SUCH_OPERATOR', 'dog'),\n  )\n  // when not matched by source can only reference the target table's columns.\n  expectError(baseQuery.whenNotMatchedBySourceAnd('species', '>', 'dog'))\n  baseQuery.whenNotMatchedBySourceAnd('age', sql`>`, 2)\n  baseQuery.whenNotMatchedBySourceAnd('person.age', '>', sql<2>`2`)\n  baseQuery.whenNotMatchedBySourceAnd('age', '>', (eb) => {\n    // already tested in many places\n    expectType<ExpressionBuilder<Database, 'person'>>(eb)\n    return eb.ref('person.age')\n  })\n  expectError(\n    baseQuery.whenNotMatchedBySourceAnd('age', '>', (eb) =>\n      eb.ref('person.gender'),\n    ),\n  )\n  baseQuery.whenNotMatchedBySourceAnd((eb) => {\n    // already tested in many places\n    expectType<ExpressionBuilder<Database, 'person'>>(eb)\n    return eb.and([])\n  })\n  expectError(baseQuery.whenNotMatchedBySourceAndRef('age'))\n  expectError(baseQuery.whenNotMatchedBySourceAndRef('NO_SUCH_COLUMN'))\n  expectError(baseQuery.whenNotMatchedBySourceAndRef('age', '>'))\n  expectError(baseQuery.whenNotMatchedBySourceAndRef('age', '>', 'string'))\n  expectError(baseQuery.whenNotMatchedBySourceAndRef('age', '>', 2))\n  baseQuery.whenNotMatchedBySourceAndRef(\n    'person.first_name',\n    '>',\n    'person.last_name',\n  )\n  // when not matched by source can only reference the target table's columns.\n  expectError(\n    baseQuery.whenNotMatchedBySourceAndRef(\n      'person.first_name',\n      '>',\n      'pet.name',\n    ),\n  )\n  expectError(\n    baseQuery.whenNotMatchedBySourceAndRef(\n      'pet.name',\n      '>',\n      'person.first_name',\n    ),\n  )\n\n  type ExpectedReturnType = MatchedThenableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    'person',\n    MergeResult\n  >\n  expectType<ExpectedReturnType>(baseQuery.whenNotMatchedBySource())\n  expectType<ExpectedReturnType>(\n    baseQuery.whenNotMatchedBySourceAnd('age', '>', 2),\n  )\n  expectType<ExpectedReturnType>(\n    baseQuery.whenNotMatchedBySourceAndRef(\n      'person.first_name',\n      '>',\n      'person.last_name',\n    ),\n  )\n}\n\nasync function testThenDelete(\n  baseQuery: MatchedThenableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    'person' | 'pet',\n    MergeResult\n  >,\n) {\n  baseQuery.thenDelete()\n  expectError(baseQuery.thenDelete('person'))\n  expectError(baseQuery.thenDelete(['person']))\n\n  expectType<\n    WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>\n  >(baseQuery.thenDelete())\n}\n\nasync function testThenDoNothing(\n  matchedBaseQuery: MatchedThenableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    'person' | 'pet',\n    MergeResult\n  >,\n  notMatchedBaseQuery: NotMatchedThenableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    MergeResult\n  >,\n) {\n  matchedBaseQuery.thenDoNothing()\n  expectError(matchedBaseQuery.thenDoNothing('person'))\n  expectError(matchedBaseQuery.thenDoNothing(['person']))\n  notMatchedBaseQuery.thenDoNothing()\n  expectError(notMatchedBaseQuery.thenDoNothing('person'))\n  expectError(notMatchedBaseQuery.thenDoNothing(['person']))\n\n  expectType<\n    WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>\n  >(matchedBaseQuery.thenDoNothing())\n  expectType<\n    WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>\n  >(notMatchedBaseQuery.thenDoNothing())\n}\n\nasync function testThenUpdate(\n  baseQuery: MatchedThenableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    'person' | 'pet',\n    MergeResult\n  >,\n  limitedBaseQuery: MatchedThenableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    'person',\n    MergeResult\n  >,\n) {\n  expectError(baseQuery.thenUpdate())\n  expectError(baseQuery.thenUpdate('person'))\n  expectError(baseQuery.thenUpdate(['person']))\n  expectError(baseQuery.thenUpdate({ age: 2 }))\n  baseQuery.thenUpdate((ub) => {\n    expectType<UpdateQueryBuilder<Database, 'person', 'person' | 'pet', never>>(\n      ub,\n    )\n    return ub\n  })\n  limitedBaseQuery.thenUpdate((ub) => {\n    expectType<UpdateQueryBuilder<Database, 'person', 'person', never>>(ub)\n    return ub\n  })\n\n  baseQuery.thenUpdateSet({ age: 2 })\n  expectError(baseQuery.thenUpdateSet({ age: 'not_a_number' }))\n  baseQuery.thenUpdateSet((eb) => {\n    expectType<ExpressionBuilder<Database, 'person' | 'pet'>>(eb)\n    return { first_name: eb.ref('pet.name') }\n  })\n  limitedBaseQuery.thenUpdateSet((eb) => {\n    expectType<ExpressionBuilder<Database, 'person'>>(eb)\n    return { last_name: eb.ref('person.first_name') }\n  })\n  baseQuery.thenUpdateSet('age', 2)\n  expectError(baseQuery.thenUpdateSet('age', 'not_a_number'))\n  baseQuery.thenUpdateSet('first_name', (eb) => {\n    expectType<ExpressionBuilder<Database, 'person' | 'pet'>>(eb)\n    return eb.ref('pet.name')\n  })\n  limitedBaseQuery.thenUpdateSet('last_name', (eb) => {\n    expectType<ExpressionBuilder<Database, 'person'>>(eb)\n    return eb.ref('person.first_name')\n  })\n\n  type ExpectedReturnType = WheneableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    MergeResult\n  >\n  expectType<ExpectedReturnType>(baseQuery.thenUpdate((ub) => ub))\n  expectType<ExpectedReturnType>(baseQuery.thenUpdateSet({ age: 2 }))\n  expectType<ExpectedReturnType>(\n    baseQuery.thenUpdateSet((eb) => ({ first_name: eb.ref('pet.name') })),\n  )\n  expectType<ExpectedReturnType>(baseQuery.thenUpdateSet('age', 2))\n}\n\nasync function testThenInsert(\n  baseQuery: NotMatchedThenableMergeQueryBuilder<\n    Database,\n    'person',\n    'pet',\n    MergeResult\n  >,\n) {\n  expectError(baseQuery.thenInsertValues())\n  expectError(baseQuery.thenInsertValues('person'))\n  expectError(baseQuery.thenInsertValues(['person']))\n  expectError(baseQuery.thenInsertValues({ age: 2 }))\n  baseQuery.thenInsertValues({ age: 2, first_name: 'Moshe', gender: 'other' })\n  expectError(\n    baseQuery.thenInsertValues({\n      age: 'not_a_number',\n      first_name: 'Moshe',\n      gender: 'other',\n    }),\n  )\n  baseQuery.thenInsertValues((eb) => {\n    expectType<ExpressionBuilder<Database, 'person' | 'pet'>>(eb)\n    return { age: 2, first_name: eb.ref('pet.name'), gender: 'other' }\n  })\n  expectError(\n    baseQuery.thenInsertValues((eb) => {\n      expectType<ExpressionBuilder<Database, 'person' | 'pet'>>(eb)\n      return {\n        age: 'not_a_number',\n        first_name: eb.ref('pet.name'),\n        gender: 'other',\n      }\n    }),\n  )\n\n  expectType<\n    WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>\n  >(\n    baseQuery.thenInsertValues({\n      age: 2,\n      first_name: 'Moshe',\n      gender: 'other',\n    }),\n  )\n}\n\nasync function testReturning(\n  baseQuery: WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>,\n) {\n  // One returning expression, target table\n  const r1 = await baseQuery.returning('person.id').execute()\n\n  expectType<{ id: number }[]>(r1)\n\n  // One returning expression, source table\n  const r2 = await baseQuery.returning('pet.name').execute()\n\n  expectType<{ name: string }[]>(r2)\n\n  // Multiple returning expressions\n  const r3 = await baseQuery\n    .returning(['person.id', 'pet.name as pet_name'])\n    .execute()\n\n  expectType<{ id: number; pet_name: string }[]>(r3)\n\n  // Non-column reference returning expressions\n  const r4 = await baseQuery\n    .returning([\n      'person.age',\n      sql<string>`concat(person.first_name, ' ', person.last_name)`.as(\n        'full_name',\n      ),\n    ])\n    .execute()\n\n  expectType<{ age: number; full_name: string }[]>(r4)\n\n  // Return all columns\n  const r5 = await baseQuery.returningAll().executeTakeFirstOrThrow()\n\n  expectType<{\n    [K in keyof Person | keyof Pet]:\n      | (K extends keyof Person ? SelectType<Person[K]> : never)\n      | (K extends keyof Pet ? SelectType<Pet[K]> : never)\n  }>(r5)\n\n  // Return all target columns\n  const r6 = await baseQuery.returningAll('person').executeTakeFirstOrThrow()\n\n  expectType<Selectable<Person>>(r6)\n\n  // Return all source columns\n  const r7 = await baseQuery.returningAll('pet').executeTakeFirstOrThrow()\n\n  expectType<Selectable<Pet>>(r7)\n\n  // Return single merge_action\n  const r8 = await baseQuery.returning(mergeAction().as('action')).execute()\n\n  expectType<{ action: 'INSERT' | 'UPDATE' | 'DELETE' }[]>(r8)\n\n  // Return multi merge_action\n  const r9 = await baseQuery\n    .returning([mergeAction().as('action'), 'person.id'])\n    .execute()\n\n  expectType<{ action: 'INSERT' | 'UPDATE' | 'DELETE'; id: number }[]>(r9)\n\n  // Non-existent column\n  expectError(baseQuery.returning('not_column'))\n  expectError(baseQuery.returning('person.not_column'))\n  expectError(baseQuery.returning('pet.not_column'))\n\n  // Non-existent prefix\n  expectError(baseQuery.returning('foo.age'))\n  expectError(baseQuery.returningAll('foo'))\n\n  // unaliased merge_action\n  expectError(baseQuery.returning(mergeAction()).execute())\n  expectError(baseQuery.returning([mergeAction(), 'person.id']).execute())\n}\n\nasync function testOutput(\n  baseQuery: WheneableMergeQueryBuilder<Database, 'person', 'pet', MergeResult>,\n) {\n  // One returning expression, deleted values\n  const r1 = await baseQuery.output('deleted.id').execute()\n\n  expectType<{ id: number }[]>(r1)\n\n  // One returning expression, inserted values\n  const r2 = await baseQuery.output('inserted.id').execute()\n\n  expectType<{ id: number }[]>(r2)\n\n  // Multiple returning expressions\n  const r3 = await baseQuery\n    .output(['deleted.id', 'inserted.first_name as fn'])\n    .execute()\n\n  expectType<{ id: number; fn: string }[]>(r3)\n\n  // Non-column reference returning expressions\n  const r4 = await baseQuery\n    .output([\n      'inserted.age',\n      sql<string>`concat(deleted.first_name, ' ', deleted.last_name)`.as(\n        'full_name',\n      ),\n    ])\n    .execute()\n\n  expectType<{ age: number; full_name: string }[]>(r4)\n\n  // Return all columns\n  const r5 = await baseQuery.outputAll('inserted').executeTakeFirstOrThrow()\n\n  expectType<Selectable<Person>>(r5)\n\n  // Non-existent column\n  expectError(baseQuery.output('inserted.not_column'))\n\n  // Without prefix\n  expectError(baseQuery.output('age'))\n  expectError(baseQuery.outputAll())\n\n  // Non-existent prefix\n  expectError(baseQuery.output('foo.age'))\n  expectError(baseQuery.outputAll('foo'))\n}\n"
  },
  {
    "path": "test/typings/test-d/postgres-json.test-d.ts",
    "content": "import {\n  jsonBuildObject,\n  type Kysely,\n  jsonArrayFrom,\n  jsonObjectFrom,\n  sql,\n  type ExpressionBuilder,\n  type NumericString,\n} from '..'\nimport type { Database } from '../shared'\nimport { expectType } from 'tsd'\n\nasync function testPostgresJsonSelects(db: Kysely<Database>) {\n  const query = db.selectFrom('person').select([\n    'person.first_name',\n\n    // Nest all person's pets.\n    (eb) =>\n      jsonArrayFrom(\n        eb\n          .selectFrom('pet')\n          .select(['name', 'species'])\n          .whereRef('owner_id', '=', 'person.id')\n          .orderBy('pet.name'),\n      ).as('pets'),\n\n    // Nest the first found dog the person owns. Only select specific fields\n    // and store it under a `doggo` field.\n    (eb) =>\n      jsonObjectFrom(\n        eb\n          .selectFrom('pet')\n          .select('name as doggo_name')\n          .whereRef('owner_id', '=', 'person.id')\n          .where('species', '=', 'dog')\n          .orderBy('name')\n          .limit(1),\n      ).as('doggo'),\n\n    // Nest an object that holds the person's formatted name.\n    (eb) =>\n      jsonBuildObject({\n        first: eb.ref('first_name'),\n        last: eb.ref('last_name'),\n        full: sql<string>`first_name || ' ' || last_name`,\n        modified_at: eb.ref('modified_at'),\n        people_with_same_name_by_2050: sql<bigint>`custom_function(first_name)`,\n        people_with_same_name_by_2050_str: sql<NumericString>`custom_function(first_name)::text`,\n        binary_thing: sql<Buffer>`another_custom_function()`,\n      }).as('name'),\n\n    // Nest other people with same first name.\n    (eb) =>\n      jsonArrayFrom(\n        eb\n          .selectFrom('person as other')\n          .where('other.id', '!=', eb.ref('person.id'))\n          .where('other.first_name', '=', eb.ref('person.first_name'))\n          .selectAll(),\n      ).as('people_same_first_name'),\n\n    // Nest an object that holds the first person that might be a match from the opposite gender and is not married.\n    (eb) =>\n      jsonObjectFrom(\n        eb\n          .selectFrom('person as match')\n          .where('match.gender', '!=', eb.ref('person.gender'))\n          .where('match.marital_status', '!=', 'married')\n          .where(\n            (eb) => eb.fn('abs', [eb('match.age', '-', eb.ref('person.age'))]),\n            '<=',\n            5,\n          )\n          .limit(1)\n          .selectAll()\n          .select(sql.lit(null).as('matched_at')),\n      ).as('potential_match'),\n  ])\n\n  const r1 = await query.execute()\n\n  expectType<\n    {\n      first_name: string\n      pets: { name: string; species: 'dog' | 'cat' }[]\n      doggo: { doggo_name: string } | null\n      name: {\n        first: string\n        last: string | null\n        full: string\n        modified_at: string\n        people_with_same_name_by_2050: number\n        people_with_same_name_by_2050_str: number\n        binary_thing: string\n      }\n      people_same_first_name: {\n        id: number\n        first_name: string\n        last_name: string | null\n        age: number\n        gender: 'male' | 'female' | 'other'\n        marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n        modified_at: string\n        deleted_at: string | null\n      }[]\n      potential_match: {\n        id: number\n        first_name: string\n        last_name: string | null\n        age: number\n        gender: 'male' | 'female' | 'other'\n        marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n        modified_at: string\n        deleted_at: string | null\n        matched_at: null\n      } | null\n    }[]\n  >(r1)\n}\n\nasync function testPostgresConditionalJsonSelects(db: Kysely<Database>) {\n  const query = db\n    .selectFrom('person')\n    .select(['person.first_name'])\n    .$if(Math.random() < 0.5, (qb) => qb.select(withPets))\n    .$if(Math.random() < 0.5, (qb) => qb.select(withDoggo))\n\n  const r1 = await query.execute()\n\n  expectType<\n    {\n      first_name: string\n      pets?: { name: string; species: 'dog' | 'cat' }[]\n      doggo?: { doggo_name: string } | null\n    }[]\n  >(r1)\n}\n\nasync function testPostgresJsonAgg(db: Kysely<Database>) {\n  const r1 = await db\n    .selectFrom('pet')\n    .innerJoin('person', 'pet.owner_id', 'person.id')\n    .select((eb) => ['pet.name', eb.fn.jsonAgg('person').as('people')])\n    .groupBy('pet.name')\n    .execute()\n\n  expectType<\n    {\n      name: string\n      people: {\n        id: number\n        first_name: string\n        last_name: string | null\n        age: number\n        gender: 'male' | 'female' | 'other'\n        marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n        modified_at: string\n        deleted_at: string | null\n      }[]\n    }[]\n  >(r1)\n\n  const r2 = await db\n    .selectFrom('pet')\n    .select((eb) => [\n      'name',\n      eb\n        .selectFrom('person')\n        .select((eb) => eb.fn.jsonAgg('person').as('people'))\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .as('people'),\n    ])\n    .execute()\n\n  expectType<\n    {\n      name: string\n      people:\n        | {\n            id: number\n            first_name: string\n            last_name: string | null\n            age: number\n            gender: 'male' | 'female' | 'other'\n            marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n            modified_at: string\n            deleted_at: string | null\n          }[]\n        | null\n    }[]\n  >(r2)\n\n  const r3 = await db\n    .selectFrom('pet')\n    .select((eb) => [\n      'name',\n      eb\n        .selectFrom('person')\n        .select((eb) => eb.fn.jsonAgg(eb.table('person')).as('people'))\n        .whereRef('pet.owner_id', '=', 'person.id')\n        .as('people'),\n    ])\n    .execute()\n\n  expectType<\n    {\n      name: string\n      people:\n        | {\n            id: number\n            first_name: string\n            last_name: string | null\n            age: number\n            gender: 'male' | 'female' | 'other'\n            marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n            modified_at: string\n            deleted_at: string | null\n          }[]\n        | null\n    }[]\n  >(r3)\n\n  const db2 = db.withTables<{\n    acquisition: {\n      id: number\n    }\n    transaction: {\n      id: number\n      acquisitionId: number\n      status: string\n    }\n  }>()\n\n  const r4 = await db2\n    .selectFrom('acquisition')\n    .leftJoin('transaction', 'transaction.acquisitionId', 'acquisition.id')\n    .select(({ ref, fn }) => [\n      'acquisition.id',\n      fn\n        .coalesce(\n          fn\n            .jsonAgg(\n              jsonBuildObject({\n                id: ref('transaction.id').$notNull(),\n                status: ref('transaction.status'),\n              }),\n            )\n            .filterWhere('transaction.id', 'is not', null),\n          sql<[]>`'[]'`,\n        )\n        .as('transactions'),\n    ])\n    .groupBy('acquisition.id')\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    id: number\n    transactions: {\n      id: number\n      status: string | null\n    }[]\n  }>(r4)\n\n  const r5 = await db\n    .selectFrom('pet')\n    .innerJoin('person', 'pet.owner_id', 'person.id')\n    .select((eb) => [\n      'name',\n      eb.fn.jsonAgg('person.modified_at').as('modified_at'),\n    ])\n    .groupBy('name')\n    .execute()\n\n  expectType<\n    {\n      name: string\n      modified_at: string[] | null\n    }[]\n  >(r5)\n}\n\nasync function testPostgresToJson(db: Kysely<Database>) {\n  const r1 = await db\n    .selectFrom('pet')\n    .innerJoin('person', 'pet.owner_id', 'person.id')\n    .select((eb) => ['name', eb.fn.toJson('person').as('person')])\n    .execute()\n\n  expectType<\n    {\n      name: string\n      person: {\n        id: number\n        first_name: string\n        last_name: string | null\n        age: number\n        gender: 'male' | 'female' | 'other'\n        marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n        modified_at: string\n        deleted_at: string | null\n      }\n    }[]\n  >(r1)\n}\n\nfunction withPets(eb: ExpressionBuilder<Database, 'person'>) {\n  return jsonArrayFrom(\n    eb\n      .selectFrom('pet')\n      .select(['name', 'species'])\n      .whereRef('owner_id', '=', 'person.id')\n      .orderBy('pet.name'),\n  ).as('pets')\n}\n\nfunction withDoggo(eb: ExpressionBuilder<Database, 'person'>) {\n  return jsonObjectFrom(\n    eb\n      .selectFrom('pet')\n      .select('name as doggo_name')\n      .whereRef('owner_id', '=', 'person.id')\n      .where('species', '=', 'dog')\n      .orderBy('name')\n      .limit(1),\n  ).as('doggo')\n}\n"
  },
  {
    "path": "test/typings/test-d/select-from.test-d.ts",
    "content": "import { type Kysely, sql } from '..'\nimport type { Database } from '../shared'\nimport { expectType, expectError } from 'tsd'\n\nasync function testFromSingle(db: Kysely<Database>) {\n  // Single table\n  const [r1] = await db.selectFrom('person').selectAll().execute()\n\n  expectType<{\n    id: number\n    first_name: string\n    last_name: string | null\n    age: number\n    gender: 'male' | 'female' | 'other'\n    modified_at: Date\n    marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n    deleted_at: Date | null\n  }>(r1)\n\n  // Table with alias\n  const [r2] = await db.selectFrom('pet as p').select('p.species').execute()\n  expectType<{ species: 'dog' | 'cat' }>(r2)\n\n  // Subquery\n  const [r3] = await db\n    .selectFrom(db.selectFrom('movie').select('movie.stars as strs').as('m'))\n    .selectAll()\n    .execute()\n  expectType<{ strs: number }>(r3)\n\n  // Subquery factory\n  const [r4] = await db\n    .selectFrom((eb) =>\n      eb.selectFrom('movie').select('movie.stars as strs').as('m'),\n    )\n    .selectAll('m')\n    .execute()\n  expectType<{ strs: number }>(r4)\n\n  // Subquery factory list\n  const [r4_2] = await db\n    .selectFrom([\n      (eb) => eb.selectFrom('movie').select('movie.stars as strs').as('m'),\n      (eb) => eb.selectFrom('pet').select('id').as('p'),\n    ])\n    .selectAll(['m', 'p'])\n    .execute()\n  expectType<{ strs: number; id: string }>(r4_2)\n\n  // Table with schema\n  const [r5] = await db\n    .selectFrom('some_schema.movie')\n    .select('stars')\n    .execute()\n  expectType<{ stars: number }>(r5)\n\n  // Table with schema and alias\n  const [r6] = await db\n    .selectFrom('some_schema.movie as m')\n    .select('m.stars')\n    .execute()\n  expectType<{ stars: number }>(r6)\n\n  // Raw expression\n  const [r7] = await db\n    .selectFrom(sql<{ one: 1 }>`(select 1 as one)`.as('o'))\n    .select('o.one')\n    .execute()\n  expectType<{ one: 1 }>(r7)\n\n  // Raw expression factory\n  const [r8] = await db\n    .selectFrom(() => sql<{ one: 1 }>`(select 1 as one)`.as('o'))\n    .select('o.one')\n    .execute()\n  expectType<{ one: 1 }>(r8)\n\n  // Deeply nested subqueries\n  const [r9] = await db\n    .selectFrom((eb) =>\n      eb\n        .selectFrom((eb2) =>\n          eb2\n            .selectFrom((eb3) =>\n              eb3.selectFrom('movie').select('stars as s').as('m1'),\n            )\n            .select('m1.s as s2')\n            .as('m2'),\n        )\n        .select('m2.s2 as s3')\n        .as('m3'),\n    )\n    .selectAll('m3')\n    .execute()\n  expectType<{ s3: number }>(r9)\n\n  // Raw expression with raw alias\n  const [r10] = await db\n    .selectFrom(sql<{ one: 1 }>`(select 1 as one)`.as<'o'>(sql`o(one)`))\n    .select('o.one')\n    .execute()\n  expectType<{ one: 1 }>(r10)\n\n  const [r11] = await db.selectFrom('book').select('id').execute()\n  expectType<{ id: number }>(r11)\n\n  // Should not be able to select animal columns from person.\n  expectError(db.selectFrom('person').select('pet.id'))\n\n  // Should not be able to start a query against non-existent table.\n  expectError(db.selectFrom('doesnt_exists'))\n\n  // Should not be able to start a query against non-existent aliased table.\n  expectError(db.selectFrom('doesnt_exists as de'))\n}\n\nasync function testFromMultiple(db: Kysely<Database>) {\n  const [r1] = await db\n    .selectFrom([\n      'person',\n      'pet as a',\n      db.selectFrom('movie').select('movie.id as movie_id').as('m'),\n      (eb) => eb.selectFrom('book').select('book.name').as('b'),\n    ])\n    .select([\n      'person.first_name',\n      'm.movie_id',\n      'a.species',\n      'b.name as book_name',\n    ])\n    .execute()\n  expectType<{\n    first_name: string\n    movie_id: string\n    species: 'dog' | 'cat'\n    book_name: string\n  }>(r1)\n\n  // Should not be able to select animal columns from person or movie.\n  expectError(db.selectFrom(['person', 'movie']).select('pet.id'))\n\n  // Should not be able to start a query against non-existent table.\n  expectError(db.selectFrom(['person', 'doesnt_exists']))\n}\n"
  },
  {
    "path": "test/typings/test-d/select-no-from.test-d.ts",
    "content": "import { type Kysely, type SqlBool, sql } from '..'\nimport type { Database } from '../shared'\nimport { expectType } from 'tsd'\n\nasync function testSelectNoFrom(db: Kysely<Database>) {\n  const r1 = await db\n    .selectNoFrom(sql<'bar'>`select 'bar'`.as('foo'))\n    .executeTakeFirstOrThrow()\n  expectType<{ foo: 'bar' }>(r1)\n\n  const r2 = await db\n    .selectNoFrom((eb) => eb(eb.val(1), '=', 1).as('very_useful'))\n    .executeTakeFirstOrThrow()\n  expectType<{ very_useful: SqlBool }>(r2)\n\n  const r3 = await db\n    .selectNoFrom([\n      sql<'bar'>`select 'bar'`.as('foo'),\n      db.selectFrom('pet').select('id').limit(1).as('pet_id'),\n    ])\n    .executeTakeFirstOrThrow()\n  expectType<{ foo: 'bar'; pet_id: string | null }>(r3)\n\n  const r4 = await db\n    .selectNoFrom((eb) => [\n      eb(eb.val(1), '=', 1).as('very_useful'),\n      eb.selectFrom('pet').select('id').limit(1).as('pet_id'),\n    ])\n    .executeTakeFirstOrThrow()\n  expectType<{ very_useful: SqlBool; pet_id: string | null }>(r4)\n}\n"
  },
  {
    "path": "test/typings/test-d/select.test-d.ts",
    "content": "import {\n  type Expression,\n  type ExpressionWrapper,\n  type Kysely,\n  type NotNull,\n  type RawBuilder,\n  type Selectable,\n  type Simplify,\n  sql,\n} from '..'\nimport type { Database, Person } from '../shared'\nimport { expectType, expectError } from 'tsd'\n\nasync function testSelectSingle(db: Kysely<Database>) {\n  const qb = db.selectFrom('person')\n\n  // Column name\n  const [r1] = await qb.select('id').execute()\n  expectType<{ id: number }>(r1)\n\n  // Table name and column name\n  const [r2] = await qb.select('person.gender').execute()\n  expectType<{ gender: 'male' | 'female' | 'other' }>(r2)\n\n  // Table name and column name with alias\n  const [r3] = await qb.select('person.age as a').execute()\n  expectType<{ a: number }>(r3)\n\n  // Raw selection\n  const [r4] = await qb\n    .select(sql<boolean>`random() > 0.5`.as('rando'))\n    .execute()\n\n  expectType<{ rando: boolean }>(r4)\n\n  // Raw selection with a dynamic alias.\n  const alias = 'col_' + Math.round(Math.random() * 1000)\n  const [r5] = await qb\n    .select(sql`random() > 0.5`.as(alias))\n    .select('first_name')\n    .execute()\n  expectType<{ first_name: string; [key: string]: unknown }>(r5)\n\n  // Subquery\n  const [r6] = await qb\n    .select(db.selectFrom('movie').select('id').as('movie_id'))\n    .execute()\n  expectType<{ movie_id: string | null }>(r6)\n\n  // Subquery factory\n  const [r7] = await qb\n    .select((qb) =>\n      qb\n        .selectFrom('movie')\n        .whereRef('movie.id', '=', 'person.id')\n        .select('movie.id')\n        .as('movie_id'),\n    )\n    .execute()\n  expectType<{ movie_id: string | null }>(r7)\n\n  // Aliased table\n  const [r8] = await db.selectFrom('pet as p').select('p.name').execute()\n  expectType<{ name: string }>(r8)\n\n  // Table with schema\n  const [r9] = await db\n    .selectFrom('some_schema.movie')\n    .select('some_schema.movie.id')\n    .execute()\n  expectType<{ id: string }>(r9)\n\n  // Aliased table with schema and selection with alias\n  const [r10] = await db\n    .selectFrom('some_schema.movie as sm')\n    .select('sm.id as identifier')\n    .execute()\n  expectType<{ identifier: string }>(r10)\n\n  // Column name with alias\n  const [r11] = await qb.select('id as identifier').execute()\n  expectType<{ identifier: number }>(r11)\n\n  // FunctionModule call\n  const [r12] = await qb\n    .select(db.fn.max('first_name').as('max_first_name'))\n    .execute()\n  expectType<{ max_first_name: string }>(r12)\n\n  // FunctionModule call through expression builder\n  const [r13] = await qb\n    .select((qb) => qb.fn.max('first_name').as('max_first_name'))\n    .execute()\n  expectType<{ max_first_name: string }>(r13)\n\n  // FunctionModule count call\n  const { count } = db.fn\n  const r14 = await qb\n    .select(count<number>('id').as('count'))\n    .executeTakeFirstOrThrow()\n  expectType<{ count: number }>(r14)\n\n  expectError(qb.select('not_property'))\n  expectError(qb.select('person.not_property'))\n  expectError(qb.select('person.not_property as np'))\n\n  // Narrow Type\n  type NarrowTarget =\n    | { queue_id: string; callback_url: null }\n    | { queue_id: null; callback_url: string }\n\n  const [r15] = await db\n    .selectFrom('action')\n    .select(['callback_url', 'queue_id'])\n    .$narrowType<NarrowTarget>()\n    .execute()\n\n  // Narrow not null\n  const [r16] = await db\n    .selectFrom('action')\n    .select(['callback_url', 'queue_id'])\n    .$narrowType<{ callback_url: NotNull }>()\n    .execute()\n\n  expectType<string>(r16.callback_url)\n  expectType<string | null>(r16.queue_id)\n\n  const [r17] = await db\n    .selectFrom('action')\n    .select(['callback_url', 'queue_id'])\n    .$narrowType<{ callback_url: NotNull; queue_id: NotNull }>()\n    .execute()\n\n  expectType<string>(r17.callback_url)\n  expectType<string>(r17.queue_id)\n\n  const expr1 = db.selectFrom('person').select('first_name').$asScalar()\n  expectType<ExpressionWrapper<Database, 'person', string>>(expr1)\n\n  const expr2 = db.selectFrom('person').select('deleted_at').$asScalar()\n  expectType<ExpressionWrapper<Database, 'person', Date | null>>(expr2)\n}\n\nasync function testSelectAll(db: Kysely<Database>) {\n  // Select all when there's only one table to select from\n  const r1 = await db.selectFrom('person').selectAll().executeTakeFirstOrThrow()\n\n  expectType<Selectable<Person>>(r1)\n\n  // Select all when there's two tables to select from\n  const r2 = await db\n    .selectFrom(['person', 'pet'])\n    .selectAll()\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    id: string | number\n    name: string\n    first_name: string\n    last_name: string | null\n    age: number\n    gender: 'other' | 'male' | 'female'\n    marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n    modified_at: Date\n    owner_id: number\n    species: 'dog' | 'cat'\n    deleted_at: Date | null\n  }>(r2)\n\n  // Select all from a single table when there are two tables to select from\n  const r3 = await db\n    .selectFrom(['person', 'pet'])\n    .selectAll('person')\n    .executeTakeFirstOrThrow()\n\n  expectType<Selectable<Person>>(r3)\n\n  // Two selectAll('table') calls should accumulate selections.\n  const [r4] = await db\n    .selectFrom([\n      db.selectFrom('person').select('id as person_id').as('per'),\n      db.selectFrom('pet').select('id as pet_id').as('pet'),\n    ])\n    .selectAll('per')\n    .selectAll('pet')\n    .execute()\n\n  expectType<{ person_id: number; pet_id: string }>(r4)\n\n  // Select all from two tables when there's two tables to select from\n  const r5 = await db\n    .selectFrom(['person', 'pet'])\n    .selectAll(['person', 'pet'])\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    id: string | number\n    name: string\n    first_name: string\n    last_name: string | null\n    age: number\n    gender: 'other' | 'male' | 'female'\n    marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null\n    modified_at: Date\n    owner_id: number\n    species: 'dog' | 'cat'\n    deleted_at: Date | null\n  }>(r5)\n}\n\nasync function testSelectMultiple(db: Kysely<Database>) {\n  const qb = db\n    .selectFrom([\n      'person',\n      (qb) =>\n        qb\n          .selectFrom('movie')\n          .select(['movie.stars', 'movie.id as movie_id'])\n          .as('m'),\n    ])\n    .innerJoin('pet as p', 'id', 'id')\n\n  const [r1] = await qb\n    .select([\n      'first_name',\n      'person.age',\n      'species as sp',\n      'p.name as pet_name',\n      'm.stars',\n      'movie_id',\n      sql<number>`random()`.as('rand1'),\n      sql<number>`random()`.as('rand2'),\n      (qb) => qb.selectFrom('pet').select('pet.id').as('sub'),\n    ])\n    .execute()\n\n  expectType<{\n    first_name: string\n    age: number\n    sp: 'dog' | 'cat'\n    pet_name: string\n    stars: number\n    movie_id: string\n    rand1: number\n    rand2: number\n    sub: string | null\n  }>(r1)\n\n  expectError(qb.select(['person.id', 'notColumn']))\n  expectError(qb.select(['person.id', 'person.notColumn']))\n  expectError(qb.select(['person.id', 'person.notColumn as foo']))\n}\n\nasync function testSelectDynamic(db: Kysely<Database>) {\n  const dynamicColumn = Math.random().toString()\n\n  // Single dynamic column name\n  const [r1] = await db\n    .selectFrom('person')\n    .select(db.dynamic.ref(dynamicColumn))\n    .execute()\n  expectType<{}>(r1)\n\n  // Single dynamic column name with column options\n  const [r2] = await db\n    .selectFrom('person')\n    .select(db.dynamic.ref<'first_name' | 'age'>(dynamicColumn))\n    .execute()\n  expectType<{ first_name: string | undefined; age: number | undefined }>(r2)\n\n  // Static selections and a dynamic one\n  const [r3] = await db\n    .selectFrom('person')\n    .select(['last_name', db.dynamic.ref(dynamicColumn)])\n    .execute()\n  expectType<{\n    last_name: string | null\n  }>(r3)\n\n  // Static selections and a dynamic one\n  const [r4] = await db\n    .selectFrom(['person', 'pet'])\n    .select([\n      'last_name',\n      db.dynamic.ref<'first_name' | 'person.age'>(dynamicColumn),\n      db.dynamic.ref<'pet.name' | 'doesnt_exist'>(dynamicColumn),\n    ])\n    .execute()\n\n  expectType<{\n    last_name: string | null\n    first_name: string | undefined\n    age: number | undefined\n    name: string | undefined\n    doesnt_exist: never | undefined\n  }>(r4)\n}\n\nasync function testIf(db: Kysely<Database>) {\n  const r = await db\n    .selectFrom('person')\n    .select('id')\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f1'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f2'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f3'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f4'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f5'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f6'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f7'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f8'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f9'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f10'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f11'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f12'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f13'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f14'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f15'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f16'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f17'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f18'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f19'))\n    .$if(Math.random() < 0.5, (qb) => qb.select('first_name as f20'))\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    id: number\n    f1?: string\n    f2?: string\n    f3?: string\n    f4?: string\n    f5?: string\n    f6?: string\n    f7?: string\n    f8?: string\n    f9?: string\n    f10?: string\n    f11?: string\n    f12?: string\n    f13?: string\n    f14?: string\n    f15?: string\n    f16?: string\n    f17?: string\n    f18?: string\n    f19?: string\n    f20?: string\n  }>(r)\n}\n\nasync function testManyNestedSubqueries(db: Kysely<Database>) {\n  const r = await db\n    .selectFrom('person as p1')\n    .select((eb1) => [\n      'p1.id',\n      jsonArrayFrom(\n        eb1\n          .selectFrom('pet as pet1')\n          .whereRef('pet1.owner_id', '=', 'p1.id')\n          .select((eb2) => [\n            'pet1.id',\n            jsonObjectFrom(\n              eb2\n                .selectFrom('person as p2')\n                .whereRef('p2.id', '=', 'pet1.owner_id')\n                .select((eb3) => [\n                  'p2.id',\n                  jsonArrayFrom(\n                    eb3\n                      .selectFrom('pet as pet2')\n                      .whereRef('pet2.owner_id', '=', 'p2.id')\n                      .select((eb4) => [\n                        'pet2.id',\n                        jsonObjectFrom(\n                          eb4\n                            .selectFrom('person as p3')\n                            .whereRef('p3.id', '=', 'pet2.owner_id')\n                            .select((eb5) => [\n                              'p3.id',\n                              jsonArrayFrom(\n                                eb5\n                                  .selectFrom('pet as pet3')\n                                  .whereRef('pet3.owner_id', '=', 'p3.id')\n                                  .select((eb6) => [\n                                    'pet3.id',\n                                    jsonObjectFrom(\n                                      eb6\n                                        .selectFrom('person as p4')\n                                        .whereRef('p4.id', '=', 'pet3.owner_id')\n                                        .select((eb7) => [\n                                          'p4.id',\n                                          jsonArrayFrom(\n                                            eb7\n                                              .selectFrom('pet as pet4')\n                                              .whereRef(\n                                                'pet4.owner_id',\n                                                '=',\n                                                'p4.id',\n                                              )\n                                              .select((eb8) => [\n                                                'pet4.id',\n                                                jsonObjectFrom(\n                                                  eb8\n                                                    .selectFrom('person as p5')\n                                                    .whereRef(\n                                                      'p5.id',\n                                                      '=',\n                                                      'pet4.owner_id',\n                                                    )\n                                                    .select('p5.id'),\n                                                ).as('owner'),\n                                              ]),\n                                          ).as('pets'),\n                                        ]),\n                                    ).as('owner'),\n                                  ]),\n                              ).as('pets'),\n                            ]),\n                        ).as('owner'),\n                      ]),\n                  ).as('pets'),\n                ]),\n            ).as('owner'),\n          ]),\n      ).as('pets'),\n    ])\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    id: number\n    pets: {\n      id: string\n      owner: {\n        id: number\n        pets: {\n          id: string\n          owner: {\n            id: number\n            pets: {\n              id: string\n              owner: {\n                id: number\n                pets: {\n                  id: string\n                  owner: { id: number } | null\n                }[]\n              } | null\n            }[]\n          } | null\n        }[]\n      } | null\n    }[]\n  }>(r)\n}\n\nexport function jsonArrayFrom<O>(\n  expr: Expression<O>,\n): RawBuilder<Simplify<O>[]> {\n  return sql`(select coalesce(json_agg(agg), '[]') from ${expr} as agg)`\n}\n\nexport function jsonObjectFrom<O>(\n  expr: Expression<O>,\n): RawBuilder<Simplify<O> | null> {\n  return sql`(select to_json(obj) from ${expr} as obj)`\n}\n"
  },
  {
    "path": "test/typings/test-d/set-operation.test-d.ts",
    "content": "import { expectError, expectType } from 'tsd'\nimport { type Kysely, sql } from '..'\nimport type { Database } from '../shared'\n\nasync function testUnion(db: Kysely<Database>) {\n  // Subquery\n  const r1 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .union(db.selectFrom('pet').select('name').select('owner_id as id'))\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r1)\n\n  // Raw expression\n  const r2 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .union(sql<{ id: number; name: string }>`(1, 'Sami')`)\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r2)\n\n  // Two subqueries\n  const r3 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .union([\n      db.selectFrom('pet').select('name').select('owner_id as id'),\n      db.selectFrom('book').select(['id', 'name']),\n    ])\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r3)\n\n  // Subquery using a callback\n  const r4 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .union((eb) => eb.selectFrom('pet').select('name').select('owner_id as id'))\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r4)\n\n  // Two subqueries using a callback\n  const r5 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .union((eb) => [\n      eb.selectFrom('pet').select('name').select('owner_id as id'),\n      eb.selectFrom('book').select(['id', 'name']),\n    ])\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r5)\n\n  // Unioned expression has a different type\n  expectError(\n    db\n      .selectFrom('person')\n      .select(['id', 'first_name as name'])\n      .where('id', 'in', [1, 2, 3])\n      .union(db.selectFrom('pet').select('name').select('owner_id')),\n  )\n}\n\nasync function testUnionAll(db: Kysely<Database>) {\n  // Subquery\n  const r1 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .unionAll(db.selectFrom('pet').select('name').select('owner_id as id'))\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r1)\n\n  // Raw expression\n  const r2 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .unionAll(sql<{ id: number; name: string }>`(1, 'Sami')`)\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r2)\n\n  // Unioned expression has a different type\n  expectError(\n    db\n      .selectFrom('person')\n      .select(['id', 'first_name as name'])\n      .where('id', 'in', [1, 2, 3])\n      .unionAll(db.selectFrom('pet').select('name').select('owner_id')),\n  )\n}\n\nasync function testIntersect(db: Kysely<Database>) {\n  // Subquery\n  const r1 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .intersect(db.selectFrom('pet').select('name').select('owner_id as id'))\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r1)\n\n  // Raw expression\n  const r2 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .intersect(sql<{ id: number; name: string }>`(1, 'Sami')`)\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r2)\n\n  // Unioned expression has a different type\n  expectError(\n    db\n      .selectFrom('person')\n      .select(['id', 'first_name as name'])\n      .where('id', 'in', [1, 2, 3])\n      .intersect(db.selectFrom('pet').select('name').select('owner_id')),\n  )\n}\n\nasync function testIntersectAll(db: Kysely<Database>) {\n  // Subquery\n  const r1 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .intersectAll(db.selectFrom('pet').select('name').select('owner_id as id'))\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r1)\n\n  // Raw expression\n  const r2 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .intersectAll(sql<{ id: number; name: string }>`(1, 'Sami')`)\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r2)\n\n  // Unioned expression has a different type\n  expectError(\n    db\n      .selectFrom('person')\n      .select(['id', 'first_name as name'])\n      .where('id', 'in', [1, 2, 3])\n      .intersectAll(db.selectFrom('pet').select('name').select('owner_id')),\n  )\n}\n\nasync function testExcept(db: Kysely<Database>) {\n  // Subquery\n  const r1 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .except(db.selectFrom('pet').select('name').select('owner_id as id'))\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r1)\n\n  // Raw expression\n  const r2 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .except(sql<{ id: number; name: string }>`(1, 'Sami')`)\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r2)\n\n  // Unioned expression has a different type\n  expectError(\n    db\n      .selectFrom('person')\n      .select(['id', 'first_name as name'])\n      .where('id', 'in', [1, 2, 3])\n      .except(db.selectFrom('pet').select('name').select('owner_id')),\n  )\n}\n\nasync function testExceptAll(db: Kysely<Database>) {\n  // Subquery\n  const r1 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .exceptAll(db.selectFrom('pet').select('name').select('owner_id as id'))\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r1)\n\n  // Raw expression\n  const r2 = await db\n    .selectFrom('person')\n    .select(['id', 'first_name as name'])\n    .where('id', 'in', [1, 2, 3])\n    .exceptAll(sql<{ id: number; name: string }>`(1, 'Sami')`)\n    .executeTakeFirstOrThrow()\n\n  expectType<{ id: number; name: string }>(r2)\n\n  // Unioned expression has a different type\n  expectError(\n    db\n      .selectFrom('person')\n      .select(['id', 'first_name as name'])\n      .where('id', 'in', [1, 2, 3])\n      .exceptAll(db.selectFrom('pet').select('name').select('owner_id')),\n  )\n}\n"
  },
  {
    "path": "test/typings/test-d/update.test-d.ts",
    "content": "import type { Kysely, UpdateResult } from '..'\nimport type { Database } from '../shared'\nimport { expectType, expectError } from 'tsd'\n\nasync function testUpdate(db: Kysely<Database>) {\n  const r1 = await db\n    .updateTable('pet')\n    .where('id', '=', '1')\n    .set({ name: 'Fluffy' })\n    .executeTakeFirst()\n  expectType<UpdateResult>(r1)\n\n  const r2 = await db\n    .updateTable('pet as p')\n    .where('p.id', '=', '1')\n    .set({ name: 'Fluffy' })\n    .executeTakeFirst()\n  expectType<UpdateResult>(r2)\n\n  const r3 = await db\n    .updateTable('pet as p')\n    .where('p.id', '=', '1')\n    .set((eb) => ({ name: eb.ref('p.id') }))\n    .executeTakeFirst()\n  expectType<UpdateResult>(r3)\n\n  const r4 = await db\n    .updateTable('pet as p')\n    .where('p.id', '=', '1')\n    .set('name', 'Fluffy')\n    .executeTakeFirst()\n  expectType<UpdateResult>(r4)\n\n  const r5 = await db\n    .updateTable('pet')\n    .from((eb) =>\n      eb\n        .selectFrom('person')\n        .select(['person.id as person_id', 'first_name as fn'])\n        .where('person.first_name', '=', 'Jennifer')\n        .forUpdate()\n        .skipLocked()\n        .as('p'),\n    )\n    .set('name', (eb) => eb.ref('p.fn'))\n    .returningAll('p')\n    .execute()\n  expectType<{ fn: string; person_id: number }[]>(r5)\n\n  // Non-existent column\n  expectError(\n    db\n      .updateTable('pet as p')\n      .where('p.id', '=', '1')\n      .set({ name: 'Fluffy', not_a_column: 'not_a_column' }),\n  )\n\n  // Non-existent column in a callback\n  expectError(\n    db\n      .updateTable('pet as p')\n      .where('p.id', '=', '1')\n      .set((eb) => ({ not_a_column: eb.val('not_a_column') })),\n  )\n\n  // GeneratedAlways column is not allowed to be updated\n  expectError(db.updateTable('book').set({ id: 1, name: 'foo' }))\n\n  db.updateTable('book').set({ name: 'bar' })\n\n  // Nullable column as undefined\n  const mutationObject: { last_name: string | undefined } = {\n    last_name: 'smith',\n  }\n\n  db.updateTable('person').set(mutationObject)\n}\n"
  },
  {
    "path": "test/typings/test-d/where.test-d.ts",
    "content": "import { type Expression, type Kysely, type SqlBool, sql } from '..'\nimport type { Database } from '../shared'\nimport { expectError } from 'tsd'\n\nfunction testWhere(db: Kysely<Database>) {\n  // Column name\n  db.selectFrom('person').where('first_name', '=', 'Arnold')\n\n  // Table and column\n  db.selectFrom('person').where('person.age', '=', 25)\n\n  // Schema, table and column\n  db.selectFrom('some_schema.movie').where('some_schema.movie.id', '=', '1')\n\n  const nullableAge = 25 as number | null\n  // Nullable RHS value\n  db.selectFrom('person').where('age', 'in', nullableAge)\n\n  // Nullable RHS reference\n  db.selectFrom('person').whereRef('first_name', '=', 'last_name')\n\n  // Nullable LHS with value\n  db.selectFrom('person').where('last_name', '=', 'Jennifer')\n\n  // Nullable LHS with reference\n  db.selectFrom('person').whereRef('last_name', '=', 'first_name')\n\n  // ColumnType reference and non-ColumnType reference.\n  db.selectFrom('pet').whereRef('id', '=', 'name')\n  db.selectFrom('pet').whereRef('name', '=', 'id')\n  db.selectFrom('pet').whereRef('id', '=', 'id')\n  db.selectFrom('pet').where((eb) => eb('name', '=', eb.ref('id')))\n  db.selectFrom('pet').where((eb) => eb('id', '=', eb.ref('name')))\n  db.selectFrom('pet').where((eb) => eb('id', '=', eb.ref('id')))\n  db.selectFrom('pet').where((eb) => eb(eb.ref('id'), '=', eb.ref('name')))\n  db.selectFrom('pet').where((eb) => eb(eb.ref('id'), '=', eb.ref('id')))\n  db.selectFrom('pet').where((eb) => eb(eb.ref('name'), '=', eb.ref('id')))\n\n  // Expression builder callback\n  db.selectFrom('movie').where(\n    (eb) => eb.selectFrom('person').select('gender'),\n    '=',\n    'female',\n  )\n\n  // Subquery in LHS\n  db.selectFrom('movie').where(\n    (eb) => eb.selectFrom('person').select('gender'),\n    '=',\n    'female',\n  )\n\n  // Nullable subquery in LHS\n  db.selectFrom('movie').where((eb) =>\n    eb.or([\n      eb('id', '=', '1'),\n      eb.and([eb('stars', '>', 2), eb('stars', '<', 5)]),\n    ]),\n  )\n\n  const firstName = 'Jennifer'\n  const lastName = 'Aniston'\n  // Dynamic `and` list in expression builder\n  db.selectFrom('person').where((eb) => {\n    const exprs: Expression<SqlBool>[] = []\n\n    if (firstName) {\n      exprs.push(eb('first_name', '=', firstName))\n    }\n\n    if (lastName) {\n      exprs.push(eb('last_name', '=', lastName))\n    }\n\n    return eb.and(exprs)\n  })\n\n  // Subquery in RHS\n  db.selectFrom('movie').where(sql<string>`${'female'}`, '=', (eb) =>\n    eb.selectFrom('person').select('gender'),\n  )\n\n  // Nullable subquery in RHS\n  db.selectFrom('person').where('first_name', 'in', (eb) =>\n    eb.selectFrom('person').select('last_name'),\n  )\n\n  // Raw expression\n  db.selectFrom('person').where('first_name', '=', sql<string>`'foo'`)\n  db.selectFrom('person').where('first_name', '=', sql<string>`'foo'`)\n  db.selectFrom('person').where(sql`whatever`, '=', 1)\n  db.selectFrom('person').where(sql`whatever`, '=', true)\n  db.selectFrom('person').where(sql`whatever`, '=', '1')\n\n  // Boolean returning select query\n  db.selectFrom('person')\n    .selectAll()\n    .where(\n      db\n        .selectFrom('pet')\n        .select((eb) => eb('name', '=', 'Doggo').as('is_doggo')),\n    )\n\n  // Boolean returning select query using a callback\n  db.selectFrom('person')\n    .selectAll()\n    .where((eb) =>\n      eb\n        .selectFrom('pet')\n        .select((eb) => eb('name', '=', 'Doggo').as('is_doggo')),\n    )\n\n  // List value\n  db.selectFrom('person').where('gender', 'in', ['female', 'male'])\n\n  // Raw operator\n  db.selectFrom('person').where('person.age', sql`lol`, 25)\n\n  // Invalid operator\n  expectError(db.selectFrom('person').where('person.age', 'lol', 25))\n\n  // Invalid table\n  expectError(db.selectFrom('person').where('movie.stars', '=', 25))\n\n  // Invalid column\n  expectError(db.selectFrom('person').where('stars', '=', 25))\n\n  // Invalid type for column\n  expectError(db.selectFrom('person').where('age', '=', '25'))\n\n  // Invalid type for column\n  expectError(db.selectFrom('person').where('gender', '=', 'not_a_gender'))\n\n  // Invalid type for column\n  expectError(\n    db.selectFrom('person').where('gender', 'in', ['female', 'not_a_gender']),\n  )\n\n  // Invalid type for column\n  expectError(\n    db.selectFrom('some_schema.movie').where('some_schema.movie.id', '=', 1),\n  )\n\n  // Invalid type for column\n  expectError(\n    db\n      .selectFrom('some_schema.movie')\n      .where(\n        (qb) => qb.selectFrom('person').select('gender'),\n        '=',\n        'not_a_gender',\n      ),\n  )\n\n  // Invalid type for column\n  expectError(db.selectFrom('person').where('first_name', '=', sql<number>`1`))\n\n  // Invalid type for column\n  expectError(db.selectFrom('person').where(sql<string>`first_name`, '=', 1))\n\n  // Non-boolean returning select query\n  expectError(\n    db\n      .selectFrom('person')\n      .selectAll()\n      .where(db.selectFrom('pet').select('name')),\n  )\n\n  // Non-boolean returning select query using a callback\n  expectError(\n    db\n      .selectFrom('person')\n      .selectAll()\n      .where((eb) => eb.selectFrom('pet').select('name')),\n  )\n}\n"
  },
  {
    "path": "test/typings/test-d/with.test-d.ts",
    "content": "import type { Kysely } from '..'\nimport type { Database } from '../shared'\nimport { expectType, expectError } from 'tsd'\n\nasync function testWith(db: Kysely<Database>) {\n  const r1 = await db\n    .with('jennifers', (db) =>\n      db.selectFrom('person').where('first_name', '=', 'Jennifer').selectAll(),\n    )\n    .with('female_jennifers', (db) =>\n      db\n        .selectFrom('jennifers')\n        .select('first_name')\n        .where('gender', '=', 'female')\n        .selectAll('jennifers')\n        .select(['first_name as fn', 'last_name as ln']),\n    )\n    .selectFrom('female_jennifers')\n    .select(['fn', 'ln'])\n    .execute()\n\n  expectType<\n    {\n      fn: string\n      ln: string | null\n    }[]\n  >(r1)\n\n  const r2 = await db\n    .with('jennifers(first_name, ln, gender)', (db) =>\n      db\n        .selectFrom('person')\n        .where('first_name', '=', 'Jennifer')\n        .select(['first_name', 'last_name as ln', 'gender']),\n    )\n    .selectFrom('jennifers')\n    .select(['first_name', 'ln'])\n    .execute()\n\n  expectType<\n    {\n      first_name: string\n      ln: string | null\n    }[]\n  >(r2)\n\n  const r3 = await db\n    .withRecursive('jennifers(first_name, ln)', (db) =>\n      db\n        .selectFrom('person')\n        .where('first_name', '=', 'Jennifer')\n        .select(['first_name', 'last_name as ln'])\n        // Recursive CTE can refer to itself.\n        .union(db.selectFrom('jennifers').select(['first_name', 'ln'])),\n    )\n    .selectFrom('jennifers')\n    .select(['first_name', 'ln'])\n    .execute()\n\n  expectType<\n    {\n      first_name: string\n      ln: string | null\n    }[]\n  >(r3)\n\n  // Using CTE builder.\n  const r4 = await db\n    .with(\n      (cte) => cte('jennifers').materialized(),\n      (db) =>\n        db\n          .selectFrom('person')\n          .where('first_name', '=', 'Jennifer')\n          .select(['first_name', 'last_name as ln', 'gender']),\n    )\n    .selectFrom('jennifers')\n    .select(['first_name', 'ln'])\n    .execute()\n\n  expectType<\n    {\n      first_name: string\n      ln: string | null\n    }[]\n  >(r4)\n\n  // https://github.com/kysely-org/kysely/issues/785\n  const r5 = await db\n    .with('person_projection', (qb) =>\n      qb\n        .selectFrom('person')\n        .select(['first_name', 'last_name'])\n        .$if(true, (qb) => qb.where('first_name', 'is not', null)),\n    )\n    .selectFrom('person_projection')\n    .selectAll()\n    .$if(true, (qb) => qb.where('first_name', 'is not', null))\n    .execute()\n\n  expectType<\n    {\n      first_name: string\n      last_name: string | null\n    }[]\n  >(r5)\n\n  // testing fix of https://github.com/kysely-org/kysely/issues/785 didn't break $if that adds columns to the projection.\n  const r6 = await db\n    .with('person_projection', (qb) =>\n      qb\n        .selectFrom('person')\n        .select(['first_name', 'last_name'])\n        .$if(true, (qb) => qb.select('age')),\n    )\n    .selectFrom('person_projection')\n    .selectAll()\n    .$if(true, (qb) => qb.where('first_name', 'is not', null))\n    .execute()\n\n  expectType<\n    {\n      first_name: string\n      last_name: string | null\n      age: number | undefined\n    }[]\n  >(r6)\n\n  // Different columns in expression and CTE name.\n  expectError(\n    db\n      .with('jennifers(first_name, last_name, gender)', (db) =>\n        db\n          .selectFrom('person')\n          .where('first_name', '=', 'Jennifer')\n          .select(['first_name', 'last_name']),\n      )\n      .selectFrom('jennifers')\n      .select(['first_name', 'last_name']),\n  )\n\n  // Unknown CTE name when using the CTE builder.\n  expectError(\n    db\n      .with(\n        (cte) => cte('jennifers').materialized(),\n        (db) =>\n          db\n            .selectFrom('person')\n            .where('first_name', '=', 'Jennifer')\n            .select(['first_name', 'last_name as ln', 'gender']),\n      )\n      .selectFrom('lollifers')\n      .select(['first_name', 'ln'])\n      .execute(),\n  )\n}\n\nasync function testManyWith(db: Kysely<Database>) {\n  const res = await db\n    .with('w1', (eb) => eb.selectFrom('person').select('first_name as fn1'))\n    .with('w2', (eb) => eb.selectFrom('person').select('first_name as fn2'))\n    .with('w3', (eb) => eb.selectFrom('person').select('first_name as fn3'))\n    .with('w4', (eb) => eb.selectFrom('person').select('first_name as fn4'))\n    .with('w5', (eb) => eb.selectFrom('person').select('first_name as fn5'))\n    .with('w6', (eb) => eb.selectFrom('person').select('first_name as fn6'))\n    .with('w7', (qb) => qb.selectFrom('person').select('first_name as fn7'))\n    .with('w8', (qb) => qb.selectFrom('person').select('first_name as fn8'))\n    .with('w9', (qb) => qb.selectFrom('person').select('first_name as fn9'))\n    .with('w10', (qb) => qb.selectFrom('person').select('first_name as fn10'))\n    .with('w11', (qb) => qb.selectFrom('person').select('first_name as fn11'))\n    .with('w12', (qb) => qb.selectFrom('person').select('first_name as fn12'))\n    .with('w13', (qb) => qb.selectFrom('person').select('first_name as fn13'))\n    .with('w14', (qb) => qb.selectFrom('person').select('first_name as fn14'))\n    .with('w15', (qb) => qb.selectFrom('person').select('first_name as fn15'))\n    .with('w16', (qb) => qb.selectFrom('person').select('first_name as fn16'))\n    .with('w17', (qb) => qb.selectFrom('person').select('first_name as fn17'))\n    .with('w18', (qb) => qb.selectFrom('person').select('first_name as fn18'))\n    .with('w19', (qb) => qb.selectFrom('person').select('first_name as fn19'))\n    .with('w20', (qb) => qb.selectFrom('person').select('first_name as fn20'))\n    .selectFrom([\n      'w1',\n      'w2',\n      'w3',\n      'w4',\n      'w5',\n      'w6',\n      'w7',\n      'w8',\n      'w9',\n      'w10',\n      'w11',\n      'w12',\n      'w13',\n      'w14',\n      'w15',\n      'w16',\n      'w17',\n      'w18',\n      'w19',\n      'w20',\n    ])\n    .selectAll()\n    .executeTakeFirstOrThrow()\n\n  expectType<{\n    fn1: string\n    fn2: string\n    fn3: string\n    fn4: string\n    fn5: string\n    fn6: string\n    fn7: string\n    fn8: string\n    fn9: string\n    fn10: string\n    fn11: string\n    fn12: string\n    fn13: string\n    fn14: string\n    fn15: string\n    fn16: string\n    fn17: string\n    fn18: string\n    fn19: string\n    fn20: string\n  }>(res)\n}\n"
  },
  {
    "path": "tsconfig-base.json",
    "content": "{\n  \"compilerOptions\": {\n    \"moduleResolution\": \"Node\",\n    \"target\": \"ESNext\",\n    \"declaration\": true,\n    \"strict\": true,\n    \"noImplicitAny\": true\n  }\n}\n"
  },
  {
    "path": "tsconfig-cjs.json",
    "content": "{\n  \"extends\": \"./tsconfig-base.json\",\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"module\": \"CommonJS\",\n    \"outDir\": \"dist/cjs\"\n  }\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"extends\": \"./tsconfig-base.json\",\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"module\": \"ESNext\",\n    \"outDir\": \"dist/esm\",\n    \"verbatimModuleSyntax\": true\n  }\n}\n"
  }
]