diff --git a/.github/goreleaser/.goreleaser-for-darwin.yaml b/.github/goreleaser/.goreleaser-for-darwin.yaml deleted file mode 100644 index b5b3da292..000000000 --- a/.github/goreleaser/.goreleaser-for-darwin.yaml +++ /dev/null @@ -1,46 +0,0 @@ ---- -project_name: stackql - -before: - hooks: - - go mod tidy - - go mod download - - go mod verify - -builds: - - id: stackql-darwin - binary: stackql - main: ./stackql/ - goos: - - darwin - goarch: - - amd64 - - arm64 - env: - - CGO_ENABLED=0 - flags: - - -trimpath - ldflags: >- - -s -w - -X github.com/stackql/stackql/internal/stackql/cmd.BuildMajorVersion={{.Major}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildMinorVersion={{.Minor}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildPatchVersion={{.Patch}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildCommitSHA={{.FullCommit}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildShortCommitSHA={{.ShortCommit}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildDate={{.Date}} - -X stackql/internal/stackql/planbuilder.PlanCacheEnabled=false - -X github.com/stackql/stackql/internal/stackql/cmd.BuildPlatform={{.Os}} - -archives: - - format: tar.gz - name_template: "stackql_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - files: - - LICENSE - - README.md - - -snapshot: - name_template: SNAPSHOT-{{ .ShortCommit }} - -checksum: - name_template: "stackql_darwin_checksums.txt" diff --git a/.github/goreleaser/.goreleaser-for-linux.yaml b/.github/goreleaser/.goreleaser-for-linux.yaml deleted file mode 100644 index fcc7385b8..000000000 --- a/.github/goreleaser/.goreleaser-for-linux.yaml +++ /dev/null @@ -1,59 +0,0 @@ ---- -project_name: stackql - -before: - hooks: - - go mod tidy - - go mod download - - go mod verify - -builds: - - id: stackql-linux - binary: stackql - main: ./stackql/ - goos: - - linux - goarch: - - amd64 - - arm64 - env: - - CGO_ENABLED=0 - flags: - - -trimpath - ldflags: >- - -s -w - -X github.com/stackql/stackql/internal/stackql/cmd.BuildMajorVersion={{.Major}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildMinorVersion={{.Minor}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildPatchVersion={{.Patch}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildCommitSHA={{.FullCommit}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildShortCommitSHA={{.ShortCommit}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildDate={{.Date}} - -X stackql/internal/stackql/planbuilder.PlanCacheEnabled=false - -X github.com/stackql/stackql/internal/stackql/cmd.BuildPlatform={{.Os}} - -archives: - - format: tar.gz - name_template: "stackql_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - files: - - LICENSE - - README.md - -snapshot: - name_template: SNAPSHOT-{{ .ShortCommit }} - -checksum: - name_template: "stackql_linux_checksums.txt" - -nfpms: - - id: stackql-nfpms - file_name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - homepage: https://stackql.io/ - maintainer: "StackQL Team " # optional - description: "Cloud asset management and automation using SQL" - license: MIT - section: golang - formats: - - deb - - rpm - - apk - - archlinux \ No newline at end of file diff --git a/.github/goreleaser/.goreleaser-for-windows.yaml b/.github/goreleaser/.goreleaser-for-windows.yaml deleted file mode 100644 index 5662f800e..000000000 --- a/.github/goreleaser/.goreleaser-for-windows.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -project_name: stackql - -before: - hooks: - - go mod tidy - - go mod download - - go mod verify - -builds: - - id: stackql-windows - binary: stackql - main: ./stackql/ - goos: - - windows - goarch: - - amd64 - env: - - CGO_ENABLED=0 - flags: - - -trimpath - ldflags: >- - -s -w - -X github.com/stackql/stackql/internal/stackql/cmd.BuildMajorVersion={{.Major}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildMinorVersion={{.Minor}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildPatchVersion={{.Patch}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildCommitSHA={{.FullCommit}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildShortCommitSHA={{.ShortCommit}} - -X github.com/stackql/stackql/internal/stackql/cmd.BuildDate={{.Date}} - -X stackql/internal/stackql/planbuilder.PlanCacheEnabled=false - -X github.com/stackql/stackql/internal/stackql/cmd.BuildPlatform={{.Os}} - -archives: - - format: zip - name_template: "stackql_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - files: - - LICENSE - - README.md - -snapshot: - name_template: SNAPSHOT-{{ .ShortCommit }} - -checksum: - name_template: "stackql_windows_checksums.txt" diff --git a/.github/workflows/build-expt.yaml b/.github/workflows/build-expt.yaml deleted file mode 100644 index 40f2b91ac..000000000 --- a/.github/workflows/build-expt.yaml +++ /dev/null @@ -1,67 +0,0 @@ -name: buildexpt - -on: - push: - tags: - - 'testing-v*' - -env: - GH_ACCESS_TOKEN: ${{ secrets.ACTIONS_PRIVATE_PACKAGE_SECRET }} - -jobs: - build-linux-binary: - runs-on: ubuntu-24.04 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Setup Go - uses: actions/setup-go@v7.0.0 - with: - go-version-file: go.mod - - name: Run Goreleaser - uses: goreleaser/goreleaser-action@v5 - with: - version: latest - args: release --clean --config .github/goreleaser/.goreleaser-for-linux.yaml --verbose - env: - GITHUB_TOKEN: ${{env.GH_ACCESS_TOKEN}} - - build-macos-binary: - runs-on: macos-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Setup Go - uses: actions/setup-go@v7.0.0 - with: - go-version-file: go.mod - - name: Run Goreleaser - uses: goreleaser/goreleaser-action@v5 - with: - version: latest - args: release --clean --config .github/goreleaser/.goreleaser-for-darwin.yaml --verbose - env: - GITHUB_TOKEN: ${{env.GH_ACCESS_TOKEN}} - - build-windows-binary: - runs-on: windows-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Setup Go - uses: actions/setup-go@v7.0.0 - with: - go-version-file: go.mod - - name: Run Goreleaser - uses: goreleaser/goreleaser-action@v5 - with: - version: latest - args: release --clean --config .github/goreleaser/.goreleaser-for-windows.yaml --verbose - env: - GITHUB_TOKEN: ${{env.GH_ACCESS_TOKEN}} \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ec7841caf..785777dee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,8 +55,8 @@ on: - '.github/workflows/contributors.yml' env: # Override this repository variable when the stable trunk changes. - STABLE_BRANCH: ${{ vars.STABLE_BRANCH || 'stable/v0.13' }} - MAIN_DOCKER_TAG_SUFFIX: ${{ vars.MAIN_DOCKER_TAG_SUFFIX || '-rc' }} + LIVE_BRANCH: ${{ vars.LIVE_BRANCH || 'stable/v0.13' }} + BUILD_SOURCE_BRANCH: ${{ github.head_ref || github.ref_name }} DOCKER_PYTHON_VERSION: '3.13' GOTESTCMD: "go test -timeout 1200s -v ./..." GOPRIVATE: github.com/stackql/* @@ -242,6 +242,8 @@ jobs: GOOS: windows GOARCH: ${{matrix.isa}} run: | + $env:BUILDPRERELEASESUFFIX = python cicd/python/prerelease_suffix.py "$env:BUILD_SOURCE_BRANCH" "$env:LIVE_BRANCH" + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } git config --global url.https://$env:GH_ACCESS_TOKEN@github.com/.insteadOf https://github.com/ $Version = convertfrom-stringdata (get-content ./cicd/version.txt -raw) $BuildMajorVersion = $Version.'MajorVersion' @@ -251,6 +253,7 @@ jobs: $env:BUILDMINORVERSION = $BuildMinorVersion # ISO-8601 UTC, matching the Linux/macOS jobs (issue #704). $env:BUILDDATE = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") + echo "BUILDPRERELEASESUFFIX: $env:BUILDPRERELEASESUFFIX" echo "BUILDMAJORVERSION=$env:BUILDMAJORVERSION" >> $GITHUB_ENV echo "BUILDMINORVERSION=$env:BUILDMINORVERSION" >> $GITHUB_ENV @@ -429,6 +432,8 @@ jobs: BUILDPATCHVERSION: ${{github.run_number}} CGO_ENABLED: 0 run: | + BUILDPRERELEASESUFFIX="$(python cicd/python/prerelease_suffix.py "$BUILD_SOURCE_BRANCH" "$LIVE_BRANCH")" + export BUILDPRERELEASESUFFIX source cicd/version.txt export BUILDMAJORVERSION="$MajorVersion" export BUILDMINORVERSION="$MinorVersion" @@ -444,6 +449,7 @@ jobs: echo "BUILDMAJORVERSION: ${BUILDMAJORVERSION}" echo "BUILDMINORVERSION: ${BUILDMINORVERSION}" echo "BUILDPATCHVERSION: ${BUILDPATCHVERSION}" + echo "BUILDPRERELEASESUFFIX: ${BUILDPRERELEASESUFFIX}" echo "BUILDBRANCH: ${BUILDBRANCH}" echo "BUILDCOMMITSHA: ${BUILDCOMMITSHA}" echo "BUILDSHORTCOMMITSHA: ${BUILDSHORTCOMMITSHA}" @@ -565,10 +571,6 @@ jobs: ./*.deb linuxtest: - # env: - # COMPOSE_BAKE: '0' - # DOCKER_BUILDKIT: '0' - # COMPOSE_DOCKER_CLI_BUILD: '0' name: Linux Test needs: @@ -665,6 +667,8 @@ jobs: BUILDPATCHVERSION: ${{github.run_number}} CGO_ENABLED: 0 run: | + BUILDPRERELEASESUFFIX="$(python cicd/python/prerelease_suffix.py "$BUILD_SOURCE_BRANCH" "$LIVE_BRANCH")" + export BUILDPRERELEASESUFFIX source cicd/version.txt export BUILDMAJORVERSION="$MajorVersion" export BUILDMINORVERSION="$MinorVersion" @@ -680,6 +684,7 @@ jobs: echo "BUILDMAJORVERSION: ${BUILDMAJORVERSION}" echo "BUILDMINORVERSION: ${BUILDMINORVERSION}" echo "BUILDPATCHVERSION: ${BUILDPATCHVERSION}" + echo "BUILDPRERELEASESUFFIX: ${BUILDPRERELEASESUFFIX}" echo "BUILDBRANCH: ${BUILDBRANCH}" echo "BUILDCOMMITSHA: ${BUILDCOMMITSHA}" echo "BUILDSHORTCOMMITSHA: ${BUILDSHORTCOMMITSHA}" @@ -1053,6 +1058,8 @@ jobs: BUILDPATCHVERSION: ${{github.run_number}} CGO_ENABLED: 0 run: | + BUILDPRERELEASESUFFIX="$(python cicd/python/prerelease_suffix.py "$BUILD_SOURCE_BRANCH" "$LIVE_BRANCH")" + export BUILDPRERELEASESUFFIX source cicd/version.txt export BUILDMAJORVERSION="$MajorVersion" export BUILDMINORVERSION="$MinorVersion" @@ -1068,6 +1075,7 @@ jobs: echo "BUILDMAJORVERSION: ${BUILDMAJORVERSION}" echo "BUILDMINORVERSION: ${BUILDMINORVERSION}" echo "BUILDPATCHVERSION: ${BUILDPATCHVERSION}" + echo "BUILDPRERELEASESUFFIX: ${BUILDPRERELEASESUFFIX}" echo "BUILDBRANCH: ${BUILDBRANCH}" echo "BUILDCOMMITSHA: ${BUILDCOMMITSHA}" echo "BUILDSHORTCOMMITSHA: ${BUILDSHORTCOMMITSHA}" @@ -1375,8 +1383,12 @@ jobs: - shell: wsl-bash {0} name: Run robot mocked functional tests + env: + WSLENV: BUILD_SOURCE_BRANCH:LIVE_BRANCH:GITHUB_REF_TYPE run: | cd /tmp/stackql-wsl-tests + BUILDPRERELEASESUFFIX="$(python3 cicd/python/prerelease_suffix.py "$BUILD_SOURCE_BRANCH" "$LIVE_BRANCH")" + export BUILDPRERELEASESUFFIX . cicd/version.txt export BUILDBRANCH="${{github.ref}}" export BUILDPATCHVERSION="${{github.run_number}}" @@ -1386,6 +1398,7 @@ jobs: echo "BUILDMAJORVERSION=$BUILDMAJORVERSION" echo "BUILDMINORVERSION=$BUILDMINORVERSION" echo "BUILDPATCHVERSION=$BUILDPATCHVERSION" + echo "BUILDPRERELEASESUFFIX=$BUILDPRERELEASESUFFIX" if [[ ! "$BUILDBRANCH" == "*develop" ]] then export BUILDPATCHVERSION="${BUILDPATCHVERSION}" @@ -1406,9 +1419,12 @@ jobs: # This is a hack because if cannot directly access secrets if: env.AZURE_CLIENT_SECRET != '' env: + WSLENV: BUILD_SOURCE_BRANCH:LIVE_BRANCH:GITHUB_REF_TYPE AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} run: | cd /tmp/stackql-wsl-tests + BUILDPRERELEASESUFFIX="$(python3 cicd/python/prerelease_suffix.py "$BUILD_SOURCE_BRANCH" "$LIVE_BRANCH")" + export BUILDPRERELEASESUFFIX . cicd/version.txt export AZURE_CLIENT_ID='${{ secrets.AZURE_CLIENT_ID }}' export AZURE_CLIENT_SECRET='${{ secrets.AZURE_CLIENT_SECRET }}' @@ -1422,6 +1438,7 @@ jobs: echo "BUILDMAJORVERSION=$BUILDMAJORVERSION" echo "BUILDMINORVERSION=$BUILDMINORVERSION" echo "BUILDPATCHVERSION=$BUILDPATCHVERSION" + echo "BUILDPRERELEASESUFFIX=$BUILDPRERELEASESUFFIX" if [[ ! "$BUILDBRANCH" == "*develop" ]] then export BUILDPATCHVERSION="${BUILDPATCHVERSION}" @@ -1518,6 +1535,8 @@ jobs: GOOS: darwin GOARCH: ${{ matrix.arch }} run: | + BUILDPRERELEASESUFFIX="$(python cicd/python/prerelease_suffix.py "$BUILD_SOURCE_BRANCH" "$LIVE_BRANCH")" + export BUILDPRERELEASESUFFIX source cicd/version.txt export BUILDMAJORVERSION="$MajorVersion" export BUILDMINORVERSION="$MinorVersion" @@ -1533,6 +1552,7 @@ jobs: echo "BUILDMAJORVERSION: ${BUILDMAJORVERSION}" echo "BUILDMINORVERSION: ${BUILDMINORVERSION}" echo "BUILDPATCHVERSION: ${BUILDPATCHVERSION}" + echo "BUILDPRERELEASESUFFIX: ${BUILDPRERELEASESUFFIX}" echo "BUILDBRANCH: ${BUILDBRANCH}" echo "BUILDCOMMITSHA: ${BUILDCOMMITSHA}" echo "BUILDSHORTCOMMITSHA: ${BUILDSHORTCOMMITSHA}" @@ -1675,7 +1695,7 @@ jobs: [ "${{ github.ref_type }}" = "branch" ] \ && ( \ [ "${{ github.ref_name }}" = "main" ] \ - || [[ "${{ github.ref_name }}" =~ ^version.* ]] \ + || [[ "$GITHUB_REF_NAME" == stable/* ]] \ ) \ && [ "${{ github.event_name }}" = "push" ] \ ) \ @@ -1701,6 +1721,8 @@ jobs: BUILDPLATFORM: ${{runner.os}} BUILDPATCHVERSION: ${{github.run_number}} run: | + BUILDPRERELEASESUFFIX="$(python cicd/python/prerelease_suffix.py "$BUILD_SOURCE_BRANCH" "$LIVE_BRANCH")" + export BUILDPRERELEASESUFFIX source cicd/version.txt BUILDMAJORVERSION=${MajorVersion} BUILDMINORVERSION=${MinorVersion} @@ -1714,6 +1736,7 @@ jobs: echo "BUILDMAJORVERSION: ${BUILDMAJORVERSION}" echo "BUILDMINORVERSION: ${BUILDMINORVERSION}" echo "BUILDPATCHVERSION: ${BUILDPATCHVERSION}" + echo "BUILDPRERELEASESUFFIX: ${BUILDPRERELEASESUFFIX}" echo "BUILDBRANCH: ${BUILDBRANCH}" echo "BUILDCOMMITSHA: ${BUILDCOMMITSHA}" echo "BUILDSHORTCOMMITSHA: ${BUILDSHORTCOMMITSHA}" @@ -1728,15 +1751,30 @@ jobs: echo "GID=${GID}" } >> "${GITHUB_ENV}" + - name: Pull Docker base images for cache purposes if: env.BUILD_IMAGE_REQUIRED == 'true' + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} run: | + if [ -n "$DOCKERHUB_USERNAME" ] && [ -n "$DOCKERHUB_TOKEN" ]; then + printf '%s' "$DOCKERHUB_TOKEN" | docker login docker.io --username "$DOCKERHUB_USERNAME" --password-stdin \ + || echo "Docker Hub login failed; attempting pull anyway." + fi docker pull --platform ${{ matrix.platform }} golang:1.27.3-bookworm || echo 'could not pull image for cache purposes' docker pull --platform ${{ matrix.platform }} ubuntu:22.04 || echo 'could not pull image for cache purposes' - name: Pull Docker image for cache purposes if: env.BUILD_IMAGE_REQUIRED == 'true' + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} run: | + if [ -n "$DOCKERHUB_USERNAME" ] && [ -n "$DOCKERHUB_TOKEN" ]; then + printf '%s' "$DOCKERHUB_TOKEN" | docker login docker.io --username "$DOCKERHUB_USERNAME" --password-stdin \ + || echo "Docker Hub login failed; attempting pull anyway." + fi docker pull --platform ${{ matrix.platform }} stackql/stackql:latest || echo 'could not pull image for cache purposes' - name: Build image precursors @@ -1762,6 +1800,7 @@ jobs: BUILDMAJORVERSION=${{env.BUILDMAJORVERSION}} BUILDMINORVERSION=${{env.BUILDMINORVERSION}} BUILDPATCHVERSION=${{env.BUILDPATCHVERSION}} + BUILDPRERELEASESUFFIX=${{env.BUILDPRERELEASESUFFIX}} platforms: ${{ matrix.platform }} target: app labels: ${{ steps.meta.outputs.labels }} @@ -1778,6 +1817,7 @@ jobs: BUILDMAJORVERSION=${{env.BUILDMAJORVERSION}} BUILDMINORVERSION=${{env.BUILDMINORVERSION}} BUILDPATCHVERSION=${{env.BUILDPATCHVERSION}} + BUILDPRERELEASESUFFIX=${{env.BUILDPRERELEASESUFFIX}} RUNTIME_IMAGE=python:${{ env.DOCKER_PYTHON_VERSION }}-slim-trixie platforms: ${{ matrix.platform }} target: app @@ -1902,7 +1942,7 @@ jobs: [ "${{ github.ref_type }}" = "branch" ] \ && ( \ [ "${{ github.ref_name }}" = "main" ] \ - || [[ "${{ github.ref_name }}" =~ ^version.* ]] \ + || [[ "$GITHUB_REF_NAME" == stable/* ]] \ ) \ && [ "${{ github.event_name }}" = "push" ] \ ) \ @@ -1933,6 +1973,10 @@ jobs: path: ${{ runner.temp }}/digests name: digests-${{ matrix.image_variant == 'python' && 'python-' || '' }}${{ env.PLATFORM_PAIR }} + - name: Set expected prerelease suffix + if: env.BUILD_IMAGE_REQUIRED == 'true' + run: python cicd/python/prerelease_suffix.py "$BUILD_SOURCE_BRANCH" "$LIVE_BRANCH" + - name: Prepare digest information if: env.BUILD_IMAGE_REQUIRED == 'true' working-directory: ${{ runner.temp }}/digests @@ -1955,16 +1999,17 @@ jobs: } >> "${GITHUB_ENV}" - - name: Login to Docker Hub - uses: docker/login-action@v4.6.0 - if: env.BUILD_IMAGE_REQUIRED == 'true' - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Pull by digest if: env.BUILD_IMAGE_REQUIRED == 'true' + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} run: | + if [ -n "$DOCKERHUB_USERNAME" ] && [ -n "$DOCKERHUB_TOKEN" ]; then + printf '%s' "$DOCKERHUB_TOKEN" | docker login docker.io --username "$DOCKERHUB_USERNAME" --password-stdin \ + || echo "Docker Hub login failed; attempting pull anyway." + fi docker pull --platform ${{ matrix.platform }} ${{ env.STACKQL_IMAGE_NAME }}@sha256:${{ env.THIS_STACKQL_DIGEST }} docker tag ${{ env.STACKQL_IMAGE_NAME }}@sha256:${{ env.THIS_STACKQL_DIGEST }} ${{ env.STACKQL_IMAGE_NAME }}:latest @@ -2049,22 +2094,34 @@ jobs: - name: Run robot mocked functional tests env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} PYTHONPATH: '${{ env.PYTHONPATH }}:${{ github.workspace }}/test/python' IS_SKIP_MCP_TEST: 'true' if: success() && env.CI_IS_EXPRESS != 'true' && env.BUILD_IMAGE_REQUIRED == 'true' && matrix.db_backend == 'sqlite' timeout-minutes: ${{ vars.DEFAULT_LONG_STEP_TIMEOUT_MIN == '' && 40 || vars.DEFAULT_LONG_STEP_TIMEOUT_MIN }} run: | + if [ -n "$DOCKERHUB_USERNAME" ] && [ -n "$DOCKERHUB_TOKEN" ]; then + printf '%s' "$DOCKERHUB_TOKEN" | docker login docker.io --username "$DOCKERHUB_USERNAME" --password-stdin \ + || echo "Docker Hub login failed; attempting tests anyway." + fi sudo rm -rf test/tmp || true mkdir -p test/tmp python cicd/python/build.py --robot-test --config='{ "variables": { "EXECUTION_PLATFORM": "docker" } }' - name: Run POSTGRES BACKEND robot mocked functional tests env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} PYTHONPATH: '${{ env.PYTHONPATH }}:${{ github.workspace }}/test/python' IS_SKIP_MCP_TEST: 'true' if: success() && env.CI_IS_EXPRESS != 'true' && matrix.platform == 'linux/amd64' && env.BUILD_IMAGE_REQUIRED == 'true' && matrix.db_backend == 'postgres_tcp' timeout-minutes: ${{ vars.DEFAULT_STEP_TIMEOUT_MIN == '' && 20 || vars.DEFAULT_STEP_TIMEOUT_MIN }} run: | + if [ -n "$DOCKERHUB_USERNAME" ] && [ -n "$DOCKERHUB_TOKEN" ]; then + printf '%s' "$DOCKERHUB_TOKEN" | docker login docker.io --username "$DOCKERHUB_USERNAME" --password-stdin \ + || echo "Docker Hub login failed; attempting tests anyway." + fi sudo rm -rf test/tmp || true mkdir -p test/tmp echo "## Stray flask apps to be killed before robot tests ##" @@ -2211,8 +2268,8 @@ jobs: [ "${{ github.ref_type }}" = "branch" ] \ && ( \ [ "${{ github.ref_name }}" = "main" ] \ - || [ "${{ github.ref_name }}" = "$STABLE_BRANCH" ] \ - || [[ "${{ github.ref_name }}" =~ ^version.* ]] \ + || [ "${{ github.ref_name }}" = "$LIVE_BRANCH" ] \ + || [[ "$GITHUB_REF_NAME" == stable/* ]] \ ) \ && [ "${{ github.event_name }}" = "push" ] \ ) \ @@ -2256,6 +2313,8 @@ jobs: BUILDPLATFORM: ${{runner.os}} BUILDPATCHVERSION: ${{github.run_number}} run: | + BUILDPRERELEASESUFFIX="$(python cicd/python/prerelease_suffix.py "$BUILD_SOURCE_BRANCH" "$LIVE_BRANCH")" + export BUILDPRERELEASESUFFIX source cicd/version.txt BUILDMAJORVERSION=${MajorVersion} BUILDMINORVERSION=${MinorVersion} @@ -2265,7 +2324,7 @@ jobs: fi if \ [ "${{ github.ref_type }}" = "branch" ] \ - && [ "${{ github.ref_name }}" = "$STABLE_BRANCH" ] \ + && [ "${{ github.ref_name }}" = "$LIVE_BRANCH" ] \ ; then SHORTHAND_DOCKER_TAG="latest" else @@ -2277,6 +2336,7 @@ jobs: echo "BUILDMAJORVERSION: ${BUILDMAJORVERSION}" echo "BUILDMINORVERSION: ${BUILDMINORVERSION}" echo "BUILDPATCHVERSION: ${BUILDPATCHVERSION}" + echo "BUILDPRERELEASESUFFIX: ${BUILDPRERELEASESUFFIX}" echo "BUILDBRANCH: ${BUILDBRANCH}" echo "BUILDCOMMITSHA: ${BUILDCOMMITSHA}" echo "BUILDSHORTCOMMITSHA: ${BUILDSHORTCOMMITSHA}" @@ -2298,10 +2358,10 @@ jobs: with: images: | ${{ env.STACKQL_IMAGE_NAME }} - # Apply the testing suffix to every main tag in one place. + # Apply the shared branch suffix after the optional Python image suffix. flavor: | latest=false - suffix=${{ matrix.variant == 'python' && format('-python{0}', env.DOCKER_PYTHON_VERSION) || '' }}${{ github.ref_type == 'branch' && github.ref_name == 'main' && env.MAIN_DOCKER_TAG_SUFFIX || '' }} + suffix=${{ matrix.variant == 'python' && format('-python{0}', env.DOCKER_PYTHON_VERSION) || '' }}${{ env.BUILDPRERELEASESUFFIX }} tags: | type=ref,event=branch type=ref,event=pr @@ -2314,8 +2374,8 @@ jobs: if: env.PUSH_IMAGE_REQUIRED == 'true' working-directory: ${{ runner.temp }}/digests env: - PYTHON_SUFFIX: ${{ matrix.variant == 'python' && format('-python{0}', env.DOCKER_PYTHON_VERSION) || '' }}${{ matrix.variant == 'python' && github.ref_type == 'branch' && github.ref_name == 'main' && env.MAIN_DOCKER_TAG_SUFFIX || '' }} - PYTHON_ALIAS: ${{ matrix.variant == 'python' && '-python3' || '' }}${{ matrix.variant == 'python' && github.ref_type == 'branch' && github.ref_name == 'main' && env.MAIN_DOCKER_TAG_SUFFIX || '' }} + PYTHON_SUFFIX: ${{ matrix.variant == 'python' && format('-python{0}', env.DOCKER_PYTHON_VERSION) || '' }}${{ matrix.variant == 'python' && env.BUILDPRERELEASESUFFIX || '' }} + PYTHON_ALIAS: ${{ matrix.variant == 'python' && '-python3' || '' }}${{ matrix.variant == 'python' && env.BUILDPRERELEASESUFFIX || '' }} run: | # Both Python tag forms are attached to the same multi-platform manifest. mapfile -t tags < <(jq -r --arg suffix "$PYTHON_SUFFIX" --arg alias "$PYTHON_ALIAS" ' diff --git a/Dockerfile b/Dockerfile index 9d2cf95bf..1db2d584e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,7 @@ FROM sourceprep AS builder ARG BUILDMAJORVERSION="1" ARG BUILDMINORVERSION="1" ARG BUILDPATCHVERSION="1" +ARG BUILDPRERELEASESUFFIX="" ARG BUILDCOMMITSHA="1" ARG BUILDSHORTCOMMITSHA="1" ARG BUILDDATE="1" @@ -40,6 +41,7 @@ ARG RUN_INTEGRATION_TESTS="1" ENV BUILDMAJORVERSION=${BUILDMAJORVERSION} ENV BUILDMINORVERSION=${BUILDMINORVERSION} ENV BUILDPATCHVERSION=${BUILDPATCHVERSION} +ENV BUILDPRERELEASESUFFIX=${BUILDPRERELEASESUFFIX} ENV BUILDCOMMITSHA=${BUILDCOMMITSHA} ENV BUILDSHORTCOMMITSHA=${BUILDSHORTCOMMITSHA} ENV BUILDDATE=${BUILDDATE} @@ -56,6 +58,8 @@ RUN cd ${SRC_DIR} \ && CGO_ENABLED=0 go build -ldflags "-X github.com/stackql/stackql/internal/stackql/cmd.BuildMajorVersion=$BUILDMAJORVERSION \ -X github.com/stackql/stackql/internal/stackql/cmd.BuildMinorVersion=$BUILDMINORVERSION \ -X github.com/stackql/stackql/internal/stackql/cmd.BuildPatchVersion=$BUILDPATCHVERSION \ + -X github.com/stackql/stackql/internal/stackql/cmd.BuildPreReleaseSuffix=$BUILDPRERELEASESUFFIX \ + -X github.com/stackql/stackql/internal/stackql/cmd.BuildPatchVersion=$BUILDPATCHVERSION \ -X github.com/stackql/stackql/internal/stackql/cmd.BuildCommitSHA=$BUILDCOMMITSHA \ -X github.com/stackql/stackql/internal/stackql/cmd.BuildShortCommitSHA=$BUILDSHORTCOMMITSHA \ -X \"github.com/stackql/stackql/internal/stackql/cmd.BuildDate=$BUILDDATE\" \ @@ -127,6 +131,7 @@ ENV TEST_ROOT_DIR=${TEST_ROOT_DIR} ARG BUILDMAJORVERSION="1" ARG BUILDMINORVERSION="1" ARG BUILDPATCHVERSION="1" +ARG BUILDPRERELEASESUFFIX="" ARG BUILDCOMMITSHA="1" ARG BUILDSHORTCOMMITSHA="1" ARG BUILDDATE="1" @@ -137,6 +142,7 @@ ARG RUN_INTEGRATION_TESTS ENV BUILDMAJORVERSION=${BUILDMAJORVERSION} ENV BUILDMINORVERSION=${BUILDMINORVERSION} ENV BUILDPATCHVERSION=${BUILDPATCHVERSION} +ENV BUILDPRERELEASESUFFIX=${BUILDPRERELEASESUFFIX} ENV BUILDCOMMITSHA=${BUILDCOMMITSHA} ENV BUILDSHORTCOMMITSHA=${BUILDSHORTCOMMITSHA} ENV BUILDDATE=${BUILDDATE} diff --git a/cicd/python/build.py b/cicd/python/build.py index 732e18939..43a785184 100644 --- a/cicd/python/build.py +++ b/cicd/python/build.py @@ -36,6 +36,7 @@ def build_stackql(verbose :bool) -> int: f'go build {"-x -v" if verbose else ""} -ldflags "-X github.com/stackql/stackql/internal/stackql/cmd.BuildMajorVersion={os.environ.get("BUILDMAJORVERSION")} ' f'-X github.com/stackql/stackql/internal/stackql/cmd.BuildMinorVersion={os.environ.get("BUILDMINORVERSION")} ' f'-X github.com/stackql/stackql/internal/stackql/cmd.BuildPatchVersion={os.environ.get("BUILDPATCHVERSION")} ' + f'-X github.com/stackql/stackql/internal/stackql/cmd.BuildPreReleaseSuffix={os.environ.get("BUILDPRERELEASESUFFIX", "")} ' f'-X github.com/stackql/stackql/internal/stackql/cmd.BuildCommitSHA={os.environ.get("BUILDCOMMITSHA", "")} ' f'-X github.com/stackql/stackql/internal/stackql/cmd.BuildShortCommitSHA={os.environ.get("BUILDCOMMITSHA", "")[0:7 or None]} ' f"-X 'github.com/stackql/stackql/internal/stackql/cmd.BuildDate={os.environ.get('BUILDDATE', '')}' " diff --git a/cicd/python/prerelease_suffix.py b/cicd/python/prerelease_suffix.py new file mode 100644 index 000000000..98b713bdb --- /dev/null +++ b/cicd/python/prerelease_suffix.py @@ -0,0 +1,29 @@ +"""Choose the build suffix once for native binaries and Docker tags.""" +import argparse +import os +from pathlib import Path + + +def prerelease_suffix(branch: str, live_branch: str, ref_type: str = "branch") -> str: + if ref_type != "branch": + return "-beta" + if branch == live_branch or branch.startswith("stable/"): + return "" + return "-rc" if branch == "main" else "-alpha" + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("branch") + parser.add_argument("live_branch") + parser.add_argument("--ref-type", choices=("branch", "tag"), default=os.environ.get("GITHUB_REF_TYPE", "branch")) + args = parser.parse_args() + suffix = prerelease_suffix(args.branch, args.live_branch, args.ref_type) + if os.environ.get("GITHUB_ENV"): + with Path(os.environ["GITHUB_ENV"]).open("a", encoding="utf-8") as output: + output.write(f"BUILDPRERELEASESUFFIX={suffix}\n") + print(suffix) + + +if __name__ == "__main__": + main() diff --git a/cicd/python/test_prerelease_suffix.py b/cicd/python/test_prerelease_suffix.py new file mode 100644 index 000000000..a2ab1912e --- /dev/null +++ b/cicd/python/test_prerelease_suffix.py @@ -0,0 +1,58 @@ +import os +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest + +from prerelease_suffix import prerelease_suffix + + +class PrereleaseSuffixTests(unittest.TestCase): + def test_branch_policy(self): + for branch, live, expected in [ + ("stable/v0.13", "stable/v0.13", ""), + ("stable/v0.12", "stable/v0.13", ""), + ("stable/older/maintenance", "stable/v0.13", ""), + ("main", "stable/v0.13", "-rc"), + ("main", "main", ""), + ("feature/example", "stable/v0.13", "-alpha"), + ("develop", "main", "-alpha"), + ("version-next", "main", "-alpha"), + ("production", "production", ""), + ]: + with self.subTest(branch=branch, live=live): + self.assertEqual(prerelease_suffix(branch, live), expected) + + def test_tags_do_not_infer_their_source_branch_from_the_name(self): + for tag in ("build-release-test-1", "main", "stable/v0.13", "unpublished-commit"): + with self.subTest(tag=tag): + self.assertEqual(prerelease_suffix(tag, "stable/v0.13", "tag"), "-beta") + + def test_cli_reads_github_tag_context(self): + with tempfile.TemporaryDirectory() as directory: + github_env = Path(directory) / "github-env" + result = subprocess.run( + [sys.executable, str(Path(__file__).with_name("prerelease_suffix.py")), "build-release-test-1", "main"], + env=dict(os.environ, GITHUB_ENV=str(github_env), GITHUB_REF_TYPE="tag"), + capture_output=True, text=True, check=True, + ) + self.assertEqual(result.stdout, "-beta\n") + self.assertEqual(github_env.read_text(encoding="utf-8"), "BUILDPRERELEASESUFFIX=-beta\n") + + def test_cli_exports_empty_and_nonempty_suffixes(self): + with tempfile.TemporaryDirectory() as directory: + github_env = Path(directory) / "github-env" + github_env.write_text("EXISTING=value\n", encoding="utf-8") + for branch, expected in [("main", "-rc"), ("stable/v0.12", ""), ("feature/test", "-alpha")]: + result = subprocess.run( + [sys.executable, str(Path(__file__).with_name("prerelease_suffix.py")), branch, "stable/v0.13"], + env=dict(os.environ, GITHUB_ENV=str(github_env), GITHUB_REF_TYPE="branch"), capture_output=True, text=True, check=True, + ) + self.assertEqual(result.stdout, expected + "\n") + self.assertEqual(github_env.read_text(encoding="utf-8"), + "EXISTING=value\nBUILDPRERELEASESUFFIX=-rc\nBUILDPRERELEASESUFFIX=\nBUILDPRERELEASESUFFIX=-alpha\n") + + +if __name__ == "__main__": + unittest.main() diff --git a/docs/developer_guide.md b/docs/developer_guide.md index dce5808fb..87b316dd1 100644 --- a/docs/developer_guide.md +++ b/docs/developer_guide.md @@ -56,6 +56,7 @@ env CGO_ENABLED=0 PLANCACHEENABLED=false go build \ -ldflags "-X github.com/stackql/stackql/internal/stackql/cmd.BuildMajorVersion=${BUILDMAJORVERSION:-1} \ -X github.com/stackql/stackql/internal/stackql/cmd.BuildMinorVersion=${BUILDMINORVERSION:-1} \ -X github.com/stackql/stackql/internal/stackql/cmd.BuildPatchVersion=${BUILDPATCHVERSION:-1} \ + -X github.com/stackql/stackql/internal/stackql/cmd.BuildPreReleaseSuffix=${BUILDPRERELEASESUFFIX} \ -X github.com/stackql/stackql/internal/stackql/cmd.BuildCommitSHA=$BUILDCOMMITSHA \ -X github.com/stackql/stackql/internal/stackql/cmd.BuildShortCommitSHA=$BUILDSHORTCOMMITSHA \ -X \"github.com/stackql/stackql/internal/stackql/cmd.BuildDate=$BUILDDATE\" \ @@ -316,3 +317,19 @@ workspace used to verify coordinated source changes is outside both repositories SQL and alias precedence, SHOW METHODS, EXEC, mutations, token endpoints and pre-request errors. It reuses the existing isolated native/Docker and SQLite/Postgres test harness; its new fixtures do not change existing provider files or Robot inputs. + +## CI prerelease suffix policy + +`cicd/python/prerelease_suffix.py ` selects the shared +`BUILDPRERELEASESUFFIX`: empty for the live branch and all `stable/**` branches, +`-rc` for non-live `main`, and `-alpha` for other branches. Tag-triggered builds +use `-beta`, since a tag does not establish its source branch; the script reads +`GITHUB_REF_TYPE` or accepts an explicit `--ref-type tag`. Set the repository +variable `LIVE_BRANCH` to change the live branch (default `stable/v0.13`). PR builds +use the source branch name. The script prints the suffix for the current build step +and appends it to `GITHUB_ENV` for later steps. + +Native build flags, Docker build arguments and published Docker tags use this same +suffix. Python image tags place it after `-python3.13` and the `-python3` alias. +All `stable/**` branches can publish Docker tags; only the live branch publishes +`latest`. Existing publication rules for other branches and release tags remain. diff --git a/internal/stackql/accessmanagement/directory.go b/internal/stackql/accessmanagement/directory.go index 9257c7e0f..05a1d95ed 100644 --- a/internal/stackql/accessmanagement/directory.go +++ b/internal/stackql/accessmanagement/directory.go @@ -34,18 +34,6 @@ func newDirectory(db *sql.DB) (principal.Directory, error) { return directory{db}, nil } -// InitializeSchema is an explicit administration operation, not part of identity resolution. -// The statements are shared by SQLite and PostgreSQL; table names never come from caller input. -func InitializeSchema(ctx context.Context, engine sqlengine.SQLEngine) error { - if engine == nil { - return errors.New("access directory requires the configured SQL engine") - } - db, err := engine.GetDB() - if err != nil { - return err - } - return initializeSchema(ctx, db) -} func initializeSchema(ctx context.Context, db *sql.DB) error { if db == nil { return errors.New("access directory requires a database") diff --git a/internal/stackql/acid/operation/operation.go b/internal/stackql/acid/operation/operation.go index 91f6ce504..60fa2f129 100644 --- a/internal/stackql/acid/operation/operation.go +++ b/internal/stackql/acid/operation/operation.go @@ -1,8 +1,6 @@ package operation import ( - "fmt" - "github.com/stackql/stackql/internal/stackql/acid/binlog" "github.com/stackql/stackql/internal/stackql/internal_data_transfer/internaldto" "github.com/stackql/stackql/internal/stackql/primitive" @@ -10,7 +8,6 @@ import ( var ( _ Operation = &reversibleOperation{} - _ Operation = &irreversibleOperation{} ) // The Operation is an abstract @@ -85,48 +82,6 @@ func (op *reversibleOperation) GetUndoLog() (binlog.LogEntry, bool) { return op.pr.GetUndoLog() } -type irreversibleOperation struct { - pr primitive.IPrimitive -} - -func (op *irreversibleOperation) Execute(pc primitive.IPrimitiveCtx) internaldto.ExecutorOutput { - res := op.pr.Execute(pc) - return res -} - -func (op *irreversibleOperation) IncidentData(id int64, ou internaldto.ExecutorOutput) error { - return op.pr.IncidentData(id, ou) -} - -func (op *irreversibleOperation) SetTxnID(id int) { - op.pr.SetTxnID(id) -} - -func (op *irreversibleOperation) SetInputAlias(alias string, id int64) error { - return op.pr.SetInputAlias(alias, id) -} - -func (op *irreversibleOperation) Undo() error { - return fmt.Errorf("irreversible operation cannot be undone") -} - -func (op *irreversibleOperation) Redo() error { - return nil -} - -// TODO: interrogate the primitive -func (op *irreversibleOperation) IsReadOnly() bool { - return op.pr.IsReadOnly() -} - -func (op *irreversibleOperation) GetRedoLog() (binlog.LogEntry, bool) { - return op.pr.GetRedoLog() -} - -func (op *irreversibleOperation) GetUndoLog() (binlog.LogEntry, bool) { - return nil, false -} - func NewReversibleOperation(pr primitive.IPrimitive) Operation { return &reversibleOperation{ pr: pr, diff --git a/internal/stackql/astindirect/cte_indirect.go b/internal/stackql/astindirect/cte_indirect.go deleted file mode 100644 index 1d8197bff..000000000 --- a/internal/stackql/astindirect/cte_indirect.go +++ /dev/null @@ -1,163 +0,0 @@ -package astindirect - -import ( - "github.com/stackql/stackql-parser/go/vt/sqlparser" - "github.com/stackql/stackql/internal/stackql/drm" - "github.com/stackql/stackql/internal/stackql/symtab" - "github.com/stackql/stackql/internal/stackql/typing" -) - -// CTE represents a Common Table Expression indirect reference. -type CTE struct { - cte *sqlparser.CommonTableExpr - name string - selectStmt sqlparser.SelectStatement - selCtx drm.PreparedStatementCtx - underlyingSymbolTable symtab.SymTab - next Indirect - isElide bool - columns []string // Column names extracted from SELECT -} - -// NewCTEIndirect creates a new CTE indirect from a CommonTableExpr. -func NewCTEIndirect(cte *sqlparser.CommonTableExpr) (Indirect, error) { - rv := &CTE{ - cte: cte, - name: cte.Name.GetRawVal(), - selectStmt: cte.Select, - underlyingSymbolTable: symtab.NewHashMapTreeSymTab(), - } - // Extract column names from the SELECT statement. - rv.columns = rv.extractColumnsFromSelect() - return rv, nil -} - -// extractColumnsFromSelect extracts column names from the CTE's SELECT statement. -func (c *CTE) extractColumnsFromSelect() []string { - var columns []string - sel, ok := c.selectStmt.(*sqlparser.Select) - if !ok { - return columns - } - for _, expr := range sel.SelectExprs { - if e, isAliased := expr.(*sqlparser.AliasedExpr); isAliased { - // Use alias if present, otherwise try to get column name - if e.As.GetRawVal() != "" { - columns = append(columns, e.As.GetRawVal()) - } else if col, isCol := e.Expr.(*sqlparser.ColName); isCol { - columns = append(columns, col.Name.GetRawVal()) - } - } - } - return columns -} - -func (c *CTE) IsElide() bool { - return c.isElide -} - -func (c *CTE) SetElide(isElide bool) { - c.isElide = isElide -} - -func (c *CTE) GetType() IndirectType { - return CTEType -} - -func (c *CTE) MatchOnParams(_ map[string]any) (Indirect, bool) { - return nil, false -} - -func (c *CTE) WithNext(next Indirect) Indirect { - c.next = next - return c.next -} - -func (c *CTE) Next() (Indirect, bool) { - return c.next, c.next != nil -} - -func (c *CTE) GetRelationalColumns() []typing.RelationalColumn { - return nil -} - -func (c *CTE) GetUnderlyingSymTab() symtab.SymTab { - return c.underlyingSymbolTable -} - -func (c *CTE) SetUnderlyingSymTab(symbolTable symtab.SymTab) { - c.underlyingSymbolTable = symbolTable -} - -func (c *CTE) GetName() string { - return c.name -} - -func (c *CTE) GetColumns() []typing.ColumnMetadata { - if c.selCtx != nil { - return c.selCtx.GetNonControlColumns() - } - // If no selCtx, create simple column metadata from extracted column names. - var cols []typing.ColumnMetadata - for _, name := range c.columns { - relCol := typing.NewRelationalColumn(name, "") - cols = append(cols, typing.NewRelayedColDescriptor(relCol, "")) - } - return cols -} - -func (c *CTE) GetColumnByName(name string) (typing.ColumnMetadata, bool) { - if c.selCtx != nil { - for _, col := range c.selCtx.GetNonControlColumns() { - if col.GetIdentifier() == name { - return col, true - } - } - return nil, false - } - // If no selCtx, check extracted column names. - for _, colName := range c.columns { - if colName == name { - relCol := typing.NewRelationalColumn(name, "") - return typing.NewRelayedColDescriptor(relCol, ""), true - } - } - return nil, false -} - -func (c *CTE) SetSelectContext(selCtx drm.PreparedStatementCtx) { - c.selCtx = selCtx -} - -func (c *CTE) GetSelectContext() drm.PreparedStatementCtx { - return c.selCtx -} - -func (c *CTE) GetTables() sqlparser.TableExprs { - return nil -} - -func (c *CTE) GetSelectAST() sqlparser.SelectStatement { - return c.selectStmt -} - -func (c *CTE) GetSelectionCtx() (drm.PreparedStatementCtx, error) { - return c.selCtx, nil -} - -func (c *CTE) Parse() error { - // CTE select statement is already parsed. - return nil -} - -func (c *CTE) GetTranslatedDDL() (string, bool) { - return "", false -} - -func (c *CTE) GetLoadDML() (string, bool) { - return "", false -} - -func (c *CTE) GetRelationalColumnByIdentifier(_ string) (typing.RelationalColumn, bool) { - return nil, false -} diff --git a/internal/stackql/astindirect/indirect.go b/internal/stackql/astindirect/indirect.go index 7329c8cf9..038f83e06 100644 --- a/internal/stackql/astindirect/indirect.go +++ b/internal/stackql/astindirect/indirect.go @@ -16,7 +16,6 @@ var ( _ Indirect = &View{} _ Indirect = &Subquery{} _ Indirect = &MaterializedView{} - _ Indirect = &CTE{} ) type IndirectType int @@ -67,15 +66,6 @@ func NewInsertRowsIndirect(insertObj *sqlparser.Insert, selCtx drm.PreparedState return rv, nil } -func NewParserExecIndirect(execObj *sqlparser.Exec, selCtx drm.PreparedStatementCtx) (Indirect, error) { - rv := &parserSelectionIndirect{ - selCtx: selCtx, - execObj: execObj, - underlyingSymbolTable: symtab.NewHashMapTreeSymTab(), - } - return rv, nil -} - func NewPhysicalTableIndirect(tableDTO internaldto.RelationDTO, sqlSystem sql_system.SQLSystem) (Indirect, error) { rv := &physicalTable{ tableDTO: tableDTO, diff --git a/internal/stackql/astvisit/specialisations.go b/internal/stackql/astvisit/specialisations.go index 8293924f1..b0a4a437e 100644 --- a/internal/stackql/astvisit/specialisations.go +++ b/internal/stackql/astvisit/specialisations.go @@ -12,59 +12,6 @@ import ( "github.com/stackql/stackql/pkg/textutil" ) -//nolint:errcheck // defer analyser uplifts -func GenerateModifiedSelectSuffix( - annotatedAST annotatedast.AnnotatedAst, - node sqlparser.SQLNode, - sqlSystem sql_system.SQLSystem, - formatter sqlparser.NodeFormatter, - namespaceCollection tablenamespace.Collection, -) string { - v := NewFragmentRewriteAstVisitor(annotatedAST, "", false, sqlSystem, formatter, namespaceCollection) - switch node := node.(type) { //nolint:gocritic // defer analyser uplifts - case *sqlparser.Select: - var options string - addIf := func(b bool, s string) { - if b { - options += s - } - } - addIf(node.Distinct, sqlparser.DistinctStr) - if node.Cache != nil { - if *node.Cache { - options += sqlparser.SQLCacheStr - } else { - options += sqlparser.SQLNoCacheStr - } - } - addIf(node.StraightJoinHint, sqlparser.StraightJoinHint) - addIf(node.SQLCalcFoundRows, sqlparser.SQLCalcFoundRowsStr) - - var groupByStr, havingStr, orderByStr, limitStr string - if node.GroupBy != nil { - node.GroupBy.Accept(v) - groupByStr = v.GetRewrittenQuery() - } - if node.Having != nil { - node.Having.Accept(v) - havingStr = v.GetRewrittenQuery() - } - if node.OrderBy != nil { - node.OrderBy.Accept(v) - orderByStr = v.GetRewrittenQuery() - } - if node.Limit != nil { - node.Limit.Accept(v) - orderByStr = v.GetRewrittenQuery() - } - rq := fmt.Sprintf("%v%v%v%v%s", - groupByStr, havingStr, orderByStr, - limitStr, node.Lock) - v.SetRewrittenQuery(rq) - } - return v.GetRewrittenQuery() -} - //nolint:errcheck // defer analyser uplifts func GenerateUnionTemplateQuery( annotatedAST annotatedast.AnnotatedAst, @@ -101,25 +48,6 @@ func GenerateUnionTemplateQuery( return v.GetRewrittenQuery() } -func GenerateModifiedWhereClause( - annotatedAST annotatedast.AnnotatedAst, - node *sqlparser.Where, - sqlSystem sql_system.SQLSystem, - formatter sqlparser.NodeFormatter, - namespaceCollection tablenamespace.Collection, -) string { - v := NewFragmentRewriteAstVisitor(annotatedAST, "", false, sqlSystem, formatter, namespaceCollection) - var whereStr string - if node != nil && node.Expr != nil { - node.Expr.Accept(v) //nolint:errcheck // defer analyser uplifts - whereStr = v.GetRewrittenQuery() - } else { - return "true" - } - v.SetRewrittenQuery(whereStr) - return v.GetRewrittenQuery() -} - func ExtractParamsFromWhereClause( annotatedAST annotatedast.AnnotatedAst, node *sqlparser.Where, @@ -135,30 +63,6 @@ func ExtractParamsFromWhereClause( return rv } -func ExtractParamsFromExecSubqueryClause( - annotatedAST annotatedast.AnnotatedAst, - node *sqlparser.ExecSubquery, -) parserutil.ParameterMap { - v := NewParamAstVisitor(annotatedAST, "", false) - if node != nil && node.Exec != nil { - node.Exec.Accept(v) //nolint:errcheck // defer analyser uplifts - } else { - return parserutil.NewParameterMap() - } - return v.GetParameters() -} - -func ExtractParamsFromFromClause( - annotatedAST annotatedast.AnnotatedAst, - node sqlparser.TableExprs, -) parserutil.ParameterMap { - v := NewParamAstVisitor(annotatedAST, "", false) - for _, expr := range node { - expr.Accept(v) //nolint:errcheck // defer analyser uplifts - } - return v.GetParameters() -} - func ExtractProviderStringsAndDetectCacheExemptMaterial( annotatedAST annotatedast.AnnotatedAst, node sqlparser.SQLNode, diff --git a/internal/stackql/buildinfo/buildinfo.go b/internal/stackql/buildinfo/buildinfo.go index f5425229b..c35a2c384 100644 --- a/internal/stackql/buildinfo/buildinfo.go +++ b/internal/stackql/buildinfo/buildinfo.go @@ -22,55 +22,63 @@ type BuildInfo interface { GetDate() string GetPlatform() string GetSemVersion() string + GetPreReleaseSuffix() string } type buildInfo struct { - majorVersion string - minorVersion string - patchVersion string - commitSHA string - shortCommitSHA string - date string - platform string - semVersion string + majorVersion string + minorVersion string + patchVersion string + preReleaseSuffix string + commitSHA string + shortCommitSHA string + date string + platform string + semVersion string } // NewBuildInfo constructs an immutable BuildInfo from the given identifiers. // SemVersion is derived from the major/minor/patch trio. -func NewBuildInfo(major, minor, patch, commitSHA, shortCommitSHA, date, platform string) BuildInfo { - return &buildInfo{ - majorVersion: major, - minorVersion: minor, - patchVersion: patch, - commitSHA: commitSHA, - shortCommitSHA: shortCommitSHA, - date: date, - platform: platform, - semVersion: fmt.Sprintf("%s.%s.%s", major, minor, patch), +func NewBuildInfo(major, minor, patch, preReleaseSuffix, commitSHA, shortCommitSHA, date, platform string) BuildInfo { + rv := &buildInfo{ + majorVersion: major, + minorVersion: minor, + patchVersion: patch, + preReleaseSuffix: preReleaseSuffix, + commitSHA: commitSHA, + shortCommitSHA: shortCommitSHA, + date: date, + platform: platform, + semVersion: fmt.Sprintf("%s.%s.%s", major, minor, patch), } + if preReleaseSuffix != "" { + rv.semVersion += preReleaseSuffix + } + return rv } -func (b *buildInfo) GetMajorVersion() string { return b.majorVersion } -func (b *buildInfo) GetMinorVersion() string { return b.minorVersion } -func (b *buildInfo) GetPatchVersion() string { return b.patchVersion } -func (b *buildInfo) GetCommitSHA() string { return b.commitSHA } -func (b *buildInfo) GetShortCommitSHA() string { return b.shortCommitSHA } -func (b *buildInfo) GetDate() string { return b.date } -func (b *buildInfo) GetPlatform() string { return b.platform } -func (b *buildInfo) GetSemVersion() string { return b.semVersion } +func (b *buildInfo) GetMajorVersion() string { return b.majorVersion } +func (b *buildInfo) GetMinorVersion() string { return b.minorVersion } +func (b *buildInfo) GetPatchVersion() string { return b.patchVersion } +func (b *buildInfo) GetCommitSHA() string { return b.commitSHA } +func (b *buildInfo) GetShortCommitSHA() string { return b.shortCommitSHA } +func (b *buildInfo) GetDate() string { return b.date } +func (b *buildInfo) GetPlatform() string { return b.platform } +func (b *buildInfo) GetSemVersion() string { return b.semVersion } +func (b *buildInfo) GetPreReleaseSuffix() string { return b.preReleaseSuffix } //nolint:gochecknoglobals // process-wide singleton; written exactly once via Init. var ( - singleton = NewBuildInfo("", "", "", "", "", "", "") + singleton = NewBuildInfo("", "", "", "", "", "", "", "") once sync.Once ) // Init publishes the process-wide BuildInfo. It is intended to be called once // from cmd/root.go's init(), after the -ldflags-populated string variables in // the cmd package have been observed. Subsequent calls are no-ops. -func Init(major, minor, patch, commitSHA, shortCommitSHA, date, platform string) { +func Init(major, minor, patch, preReleaseSuffix, commitSHA, shortCommitSHA, date, platform string) { once.Do(func() { - singleton = NewBuildInfo(major, minor, patch, commitSHA, shortCommitSHA, date, platform) + singleton = NewBuildInfo(major, minor, patch, preReleaseSuffix, commitSHA, shortCommitSHA, date, platform) }) } diff --git a/internal/stackql/cmd/root.go b/internal/stackql/cmd/root.go index 7951fd4cc..5babb53bf 100644 --- a/internal/stackql/cmd/root.go +++ b/internal/stackql/cmd/root.go @@ -48,13 +48,14 @@ import ( // //nolint:revive,gochecknoglobals // populated by -ldflags at build time var ( - BuildMajorVersion string = "" - BuildMinorVersion string = "" - BuildPatchVersion string = "" - BuildCommitSHA string = "" - BuildShortCommitSHA string = "" - BuildDate string = "" - BuildPlatform string = "" + BuildMajorVersion string = "" + BuildMinorVersion string = "" + BuildPatchVersion string = "" + BuildPreReleaseSuffix string = "" + BuildCommitSHA string = "" + BuildShortCommitSHA string = "" + BuildDate string = "" + BuildPlatform string = "" ) func getSemver() string { @@ -173,6 +174,7 @@ func init() { BuildMajorVersion, BuildMinorVersion, BuildPatchVersion, + BuildPreReleaseSuffix, BuildCommitSHA, BuildShortCommitSHA, buildDate, diff --git a/internal/stackql/config/config.go b/internal/stackql/config/config.go index 5e3a433ba..0aa8ff638 100644 --- a/internal/stackql/config/config.go +++ b/internal/stackql/config/config.go @@ -61,10 +61,6 @@ func GetDefaultViperConfigFileName() string { return defaultConfigFileName } -func GetDefaultKeyFilePath() string { - return "" -} - func GetDefaultProviderCacheDirFileMode() uint32 { if runtime.GOOS == "windows" { return defaultWindowsConfigCacheDirFileMode diff --git a/internal/stackql/drm/prepared_statement_ctx.go b/internal/stackql/drm/prepared_statement_ctx.go index d22fd6920..089b8f607 100644 --- a/internal/stackql/drm/prepared_statement_ctx.go +++ b/internal/stackql/drm/prepared_statement_ctx.go @@ -2,8 +2,6 @@ package drm import ( "github.com/stackql/stackql/internal/stackql/internal_data_transfer/internaldto" - "github.com/stackql/stackql/internal/stackql/sql_system" - "github.com/stackql/stackql/internal/stackql/tablenamespace" "github.com/stackql/stackql/internal/stackql/typing" ) @@ -28,24 +26,16 @@ type PreparedStatementCtx interface { } type standardPreparedStatementCtx struct { - query string - kind string // string annotation applicable only in some cases eg UNION [ALL] - genIDControlColName string - sessionIDControlColName string - TableNames []string - txnIDControlColName string - insIDControlColName string - insEncodedColName string - nonControlColumns []typing.ColumnMetadata - ctrlColumnRepeats int - txnCtrlCtrs internaldto.TxnControlCounters - selectTxnCtrlCtrs []internaldto.TxnControlCounters - namespaceCollection tablenamespace.Collection - sqlSystem sql_system.SQLSystem - indirectContexts []PreparedStatementCtx - parameters map[string]interface{} - aliasToTccMap map[string][]internaldto.TxnControlCounters - aliasOrdering []string + query string + kind string // string annotation applicable only in some cases eg UNION [ALL] + TableNames []string + nonControlColumns []typing.ColumnMetadata + ctrlColumnRepeats int + txnCtrlCtrs internaldto.TxnControlCounters + selectTxnCtrlCtrs []internaldto.TxnControlCounters + indirectContexts []PreparedStatementCtx + aliasToTccMap map[string][]internaldto.TxnControlCounters + aliasOrdering []string } func (ps *standardPreparedStatementCtx) GetOrderedTccs() []internaldto.TxnControlCounters { @@ -110,42 +100,6 @@ func (ps *standardPreparedStatementCtx) GetAllCtrlCtrs() []internaldto.TxnContro return rv } -func NewPreparedStatementCtx( - query string, - kind string, - genIDControlColName string, - sessionIDControlColName string, - tableNames []string, - txnIDControlColName string, - insIDControlColName string, - insEncodedColName string, - nonControlColumns []typing.ColumnMetadata, - ctrlColumnRepeats int, - txnCtrlCtrs internaldto.TxnControlCounters, - secondaryCtrs []internaldto.TxnControlCounters, - namespaceCollection tablenamespace.Collection, - sqlSystem sql_system.SQLSystem, - parameters map[string]interface{}, -) PreparedStatementCtx { - return &standardPreparedStatementCtx{ - query: query, - kind: kind, - genIDControlColName: genIDControlColName, - sessionIDControlColName: sessionIDControlColName, - TableNames: tableNames, - txnIDControlColName: txnIDControlColName, - insIDControlColName: insIDControlColName, - insEncodedColName: insEncodedColName, - nonControlColumns: nonControlColumns, - ctrlColumnRepeats: ctrlColumnRepeats, - txnCtrlCtrs: txnCtrlCtrs, - selectTxnCtrlCtrs: secondaryCtrs, - namespaceCollection: namespaceCollection, - sqlSystem: sqlSystem, - parameters: parameters, - } -} - func NewQueryOnlyPreparedStatementCtx(query string, nonControlCols []typing.ColumnMetadata) PreparedStatementCtx { return &standardPreparedStatementCtx{query: query, nonControlColumns: nonControlCols, ctrlColumnRepeats: 0} } diff --git a/internal/stackql/internal_data_transfer/builder_input/builder_input.go b/internal/stackql/internal_data_transfer/builder_input/builder_input.go index d9cb23f8a..e89d080ab 100644 --- a/internal/stackql/internal_data_transfer/builder_input/builder_input.go +++ b/internal/stackql/internal_data_transfer/builder_input/builder_input.go @@ -9,7 +9,6 @@ import ( "github.com/stackql/stackql/internal/stackql/primitivegraph" "github.com/stackql/stackql/internal/stackql/provider" "github.com/stackql/stackql/internal/stackql/streaming" - "github.com/stackql/stackql/internal/stackql/tableinsertioncontainer" "github.com/stackql/stackql/internal/stackql/tablemetadata" ) @@ -52,33 +51,30 @@ type BuilderInput interface { SetIsTargetPhysicalTable(isPhysical bool) SetTxnCtrlCtrs(internaldto.TxnControlCounters) GetTxnCtrlCtrs() (internaldto.TxnControlCounters, bool) - GetTableInsertionContainer() (tableinsertioncontainer.TableInsertionContainer, bool) - SetTableInsertionContainer(tableinsertioncontainer.TableInsertionContainer) SetInsertCtx(insertCtx drm.PreparedStatementCtx) GetInsertCtx() (drm.PreparedStatementCtx, bool) } type builderInput struct { - graphHolder primitivegraph.PrimitiveGraphHolder - handlerCtx handler.HandlerContext - paramMap map[int]map[string]interface{} - tbl tablemetadata.ExtendedTableMetadata - dependencyNode primitivegraph.PrimitiveNode - commentDirectives sqlparser.CommentDirectives - isAwait bool - isReturning bool - verb string - inputAlias string - isUndo bool - node sqlparser.SQLNode - paramMapStream streaming.MapStream - prov provider.IProvider - annotatedAst annotatedast.AnnotatedAst - isTargetPhysical bool - txnCtrlCtrs internaldto.TxnControlCounters - tableInsertionContainer tableinsertioncontainer.TableInsertionContainer - insertCtx drm.PreparedStatementCtx - requiredDataRequestKey string + graphHolder primitivegraph.PrimitiveGraphHolder + handlerCtx handler.HandlerContext + paramMap map[int]map[string]interface{} + tbl tablemetadata.ExtendedTableMetadata + dependencyNode primitivegraph.PrimitiveNode + commentDirectives sqlparser.CommentDirectives + isAwait bool + isReturning bool + verb string + inputAlias string + isUndo bool + node sqlparser.SQLNode + paramMapStream streaming.MapStream + prov provider.IProvider + annotatedAst annotatedast.AnnotatedAst + isTargetPhysical bool + txnCtrlCtrs internaldto.TxnControlCounters + insertCtx drm.PreparedStatementCtx + requiredDataRequestKey string } func NewBuilderInput( @@ -122,14 +118,6 @@ func (bi *builderInput) SetIsReturning(isReturning bool) { bi.isReturning = isReturning } -func (bi *builderInput) GetTableInsertionContainer() (tableinsertioncontainer.TableInsertionContainer, bool) { - return bi.tableInsertionContainer, bi.tableInsertionContainer != nil -} - -func (bi *builderInput) SetTableInsertionContainer(ti tableinsertioncontainer.TableInsertionContainer) { - bi.tableInsertionContainer = ti -} - func (bi *builderInput) SetTxnCtrlCtrs(tcc internaldto.TxnControlCounters) { bi.txnCtrlCtrs = tcc } diff --git a/internal/stackql/internal_data_transfer/internaldto/heirarchy.go b/internal/stackql/internal_data_transfer/internaldto/heirarchy.go deleted file mode 100644 index 625e8cfe4..000000000 --- a/internal/stackql/internal_data_transfer/internaldto/heirarchy.go +++ /dev/null @@ -1,33 +0,0 @@ -package internaldto - -import ( - "fmt" - - "github.com/stackql/stackql-parser/go/vt/sqlparser" -) - -func generatePutativelyUniqueTableName(node sqlparser.TableName) string { - if node.IsEmpty() { - return "" - } - retVal := "" - if !node.QualifierThird.IsEmpty() { - retVal += fmt.Sprintf("%s.", node.QualifierThird.GetRawVal()) - } - if !node.QualifierSecond.IsEmpty() { - retVal += fmt.Sprintf("%s.", node.QualifierSecond.GetRawVal()) - } - if !node.Qualifier.IsEmpty() { - retVal += fmt.Sprintf("%s.", node.Qualifier.GetRawVal()) - } - retVal += node.Name.GetRawVal() - return retVal -} - -func GeneratePutativelyUniqueColumnID(node sqlparser.TableName, colName string) string { - tableID := generatePutativelyUniqueTableName(node) - if tableID == "" { - return colName - } - return fmt.Sprintf("%s.%s", tableID, colName) -} diff --git a/internal/stackql/internal_data_transfer/relationaldto/relational_table.go b/internal/stackql/internal_data_transfer/relationaldto/relational_table.go deleted file mode 100644 index 03421baa5..000000000 --- a/internal/stackql/internal_data_transfer/relationaldto/relational_table.go +++ /dev/null @@ -1,35 +0,0 @@ -package relationaldto - -import ( - "github.com/stackql/stackql/internal/stackql/internal_data_transfer/internaldto" - "github.com/stackql/stackql/internal/stackql/typing" -) - -var ( - _ RelationalTable = &standardRelationalTable{} -) - -type RelationalTable interface { - GetAlias() string - GetBaseName() string - GetColumns() []typing.RelationalColumn - GetName() (string, error) - GetView() (internaldto.RelationDTO, bool) - PushBackColumn(typing.RelationalColumn) - WithAlias(alias string) RelationalTable -} - -func NewRelationalTable(hIDs internaldto.HeirarchyIdentifiers, discoveryID int, name, baseName string) RelationalTable { - return &standardRelationalTable{ - hIDs: hIDs, - name: name, - baseName: baseName, - discoveryID: discoveryID, - } -} - -func NewRelationalView(viewDTO internaldto.RelationDTO) RelationalTable { - return &standardRelationalTable{ - viewDTO: viewDTO, - } -} diff --git a/internal/stackql/internal_data_transfer/relationaldto/standard_relational_table.go b/internal/stackql/internal_data_transfer/relationaldto/standard_relational_table.go deleted file mode 100644 index b88f4a96c..000000000 --- a/internal/stackql/internal_data_transfer/relationaldto/standard_relational_table.go +++ /dev/null @@ -1,54 +0,0 @@ -package relationaldto - -import ( - "github.com/stackql/stackql/internal/stackql/internal_data_transfer/internaldto" - "github.com/stackql/stackql/internal/stackql/typing" -) - -type standardRelationalTable struct { - alias string - name string - baseName string - discoveryID int - hIDs internaldto.HeirarchyIdentifiers - viewDTO internaldto.RelationDTO - columns []typing.RelationalColumn -} - -func (rt *standardRelationalTable) WithView(viewDTO internaldto.RelationDTO) RelationalTable { - rt.viewDTO = viewDTO - return rt -} - -func (rt *standardRelationalTable) GetName() (string, error) { - return rt.name, nil -} - -func (rt *standardRelationalTable) GetBaseName() string { - return rt.baseName -} - -func (rt *standardRelationalTable) IsView() bool { - return false -} - -func (rt *standardRelationalTable) GetAlias() string { - return rt.alias -} - -func (rt *standardRelationalTable) WithAlias(alias string) RelationalTable { - rt.alias = alias - return rt -} - -func (rt *standardRelationalTable) GetView() (internaldto.RelationDTO, bool) { - return rt.viewDTO, rt.viewDTO != nil -} - -func (rt *standardRelationalTable) GetColumns() []typing.RelationalColumn { - return rt.columns -} - -func (rt *standardRelationalTable) PushBackColumn(col typing.RelationalColumn) { - rt.columns = append(rt.columns, col) -} diff --git a/internal/stackql/namemangle/name_mangle.go b/internal/stackql/namemangle/name_mangle.go deleted file mode 100644 index 298ba0ac6..000000000 --- a/internal/stackql/namemangle/name_mangle.go +++ /dev/null @@ -1,76 +0,0 @@ -package name_mangle //nolint:revive,stylecheck // preference - -import ( - "fmt" - "regexp" - "strings" -) - -var ( - _ NameMangler = &standardNameMutator{} - _ NameUnmangler = &standardNameMutator{} -) - -var ( - //nolint:revive // prefer explicit - standardUnmangleRegexp *regexp.Regexp = regexp.MustCompile(`([\S]+)_([0-9]+)$`) -) - -type NameMangler interface { - MangleName(string, ...any) string -} - -type NameUnmangler interface { - UnmangleName(string) (string, error) -} - -func NewViewNameMangler() NameMangler { - return &standardNameMutator{} -} - -func NewViewNameUnmangler() NameUnmangler { - return &standardNameMutator{} -} - -type standardNameMutator struct { -} - -func (v *standardNameMutator) MangleName(base string, varargs ...any) string { - if len(varargs) == 0 { - return base - } - if len(varargs) == 1 { - i, isInt := varargs[0].(int) - if isInt && i == 0 { - return base - } - } - var sb strings.Builder - sb.WriteString(base) - for _, arg := range varargs { - sb.WriteString(fmt.Sprintf("_%v", arg)) - } - return sb.String() -} - -func (v *standardNameMutator) UnmangleName(base string) (string, error) { - matches := standardUnmangleRegexp.FindStringSubmatch(base) - if len(matches) == 0 { - return base, nil - } - if len(matches) != 3 { //nolint:mnd // 3 is the expected length - return "", fmt.Errorf("could not unmangle %s", base) - } - return matches[1], nil -} - -// func (v *standardNameMutator) GetWhereClause(base string) string { -// matches := standardUnmangleRegexp.FindStringSubmatch(base) -// if len(matches) == 0 { -// return base, nil -// } -// if len(matches) != 3 { //nolint:mnd // 3 is the expected length -// return "", fmt.Errorf("could not unmangle %s", base) -// } -// return matches[1], nil -// } diff --git a/internal/stackql/netutils/http_proxy.go b/internal/stackql/netutils/http_proxy.go index c71561b84..257b28714 100644 --- a/internal/stackql/netutils/http_proxy.go +++ b/internal/stackql/netutils/http_proxy.go @@ -7,7 +7,6 @@ import ( "net/http" "net/url" "os" - "time" ) type HTTPContext interface { @@ -77,21 +76,6 @@ func getRoundTripper(httpCtx HTTPContext, existingTransport http.RoundTripper) h return rt } -func GetHTTPClient(httpCtx HTTPContext, existingClient *http.Client) *http.Client { - return getHTTPClient(httpCtx, existingClient) -} - -func getHTTPClient(httpCtx HTTPContext, existingClient *http.Client) *http.Client { - var rt http.RoundTripper - if existingClient != nil && existingClient.Transport != nil { - rt = existingClient.Transport - } - return &http.Client{ - Timeout: time.Second * time.Duration(httpCtx.GetAPIRequestTimeout()), - Transport: getRoundTripper(httpCtx, rt), - } -} - func getCertPool(localCaBundlePath string) (*x509.CertPool, error) { var lb []byte var err error diff --git a/internal/stackql/output/output.go b/internal/stackql/output/output.go index 356c75600..0804b2768 100644 --- a/internal/stackql/output/output.go +++ b/internal/stackql/output/output.go @@ -30,18 +30,6 @@ type IOutputWriter interface { WriteError(error, string) error } -type IColumnOrderer interface { - GetColumnOrder() []string -} - -type BasicColumnOrderer struct { - ordering []string -} - -func (bco *BasicColumnOrderer) GetColumnOrder() []string { - return bco.ordering -} - func writeStderrError(writer io.Writer, err error) error { _, e := fmt.Fprintln(writer, err.Error()) return e diff --git a/internal/stackql/parserutil/columnar_reference.go b/internal/stackql/parserutil/columnar_reference.go index d7a7cd801..4035d440f 100644 --- a/internal/stackql/parserutil/columnar_reference.go +++ b/internal/stackql/parserutil/columnar_reference.go @@ -6,6 +6,14 @@ import ( "github.com/stackql/stackql-parser/go/vt/sqlparser" ) +type ParamSourceType int + +const ( + UnknownParam ParamSourceType = iota + WhereParam + JoinOnParam +) + // An abstract data type where the // underlying datum should in some way // represent a column or parameter. @@ -22,12 +30,12 @@ type ColumnarReference interface { SourceType() ParamSourceType } -type StandardColumnarReference struct { +type standardColumnarReference struct { k interface{} sourceType ParamSourceType } -func (cr StandardColumnarReference) Abbreviate() (string, bool) { +func (cr standardColumnarReference) Abbreviate() (string, bool) { switch kv := cr.Value().(type) { case *sqlparser.ColName: return kv.Name.GetRawVal(), true @@ -36,15 +44,15 @@ func (cr StandardColumnarReference) Abbreviate() (string, bool) { } } -func (cr StandardColumnarReference) SourceType() ParamSourceType { +func (cr standardColumnarReference) SourceType() ParamSourceType { return cr.sourceType } -func (cr StandardColumnarReference) Value() interface{} { +func (cr standardColumnarReference) Value() interface{} { return cr.k } -func (cr StandardColumnarReference) Alias() string { +func (cr standardColumnarReference) Alias() string { switch t := cr.k.(type) { case *sqlparser.ColName: return t.Qualifier.GetRawVal() @@ -55,7 +63,7 @@ func (cr StandardColumnarReference) Alias() string { } } -func (cr StandardColumnarReference) Name() string { +func (cr standardColumnarReference) Name() string { switch t := cr.k.(type) { case *sqlparser.ColName: return t.Name.GetRawVal() @@ -66,7 +74,7 @@ func (cr StandardColumnarReference) Name() string { } } -func (cr StandardColumnarReference) String() string { +func (cr standardColumnarReference) String() string { switch t := cr.k.(type) { case *sqlparser.ColName: return t.GetRawVal() @@ -77,30 +85,26 @@ func (cr StandardColumnarReference) String() string { } } -func (cr StandardColumnarReference) iColumnarReference() {} +func (cr standardColumnarReference) iColumnarReference() {} func NewUnknownTypeColumnarReference(k interface{}) (ColumnarReference, error) { return newColumnarReference(k, UnknownParam) } -func NewColumnarReference(k interface{}, sourceType ParamSourceType) (ColumnarReference, error) { - return newColumnarReference(k, sourceType) -} - // Enforces supported underlying data invariant. func newColumnarReference(k interface{}, sourceType ParamSourceType) (ColumnarReference, error) { switch k := k.(type) { case *sqlparser.ColName: - return StandardColumnarReference{k: k, sourceType: sourceType}, nil + return standardColumnarReference{k: k, sourceType: sourceType}, nil case sqlparser.ColIdent: kp := &k - return StandardColumnarReference{k: kp, sourceType: sourceType}, nil + return standardColumnarReference{k: kp, sourceType: sourceType}, nil default: return nil, fmt.Errorf("cannot accomodate columnar reference for type = '%T'", k) } } -func (cr StandardColumnarReference) GetStringKey() string { +func (cr standardColumnarReference) GetStringKey() string { switch k := cr.k.(type) { case *sqlparser.ColName: return k.GetRawVal() diff --git a/internal/stackql/parserutil/insert_intel.go b/internal/stackql/parserutil/insert_intel.go index e3b5757b4..ade2220ad 100644 --- a/internal/stackql/parserutil/insert_intel.go +++ b/internal/stackql/parserutil/insert_intel.go @@ -1,8 +1,6 @@ package parserutil import ( - "strings" - "github.com/stackql/stackql-parser/go/vt/sqlparser" ) @@ -23,31 +21,3 @@ func IsSelectDynamic(node *sqlparser.Select) bool { } return false } - -func isScalarSQLVal(expr *sqlparser.SQLVal) bool { - //nolint:exhaustive // this is not exhaustive, but it is sufficient for our use cases - switch expr.Type { - case sqlparser.IntVal, sqlparser.FloatVal, sqlparser.HexNum, sqlparser.HexVal, sqlparser.ValArg: - return true - case sqlparser.StrVal: - valStr := strings.ToLower(string(expr.Val)) - if valStr == "true" || valStr == "false" || valStr == "null" { - return true - } - return false - default: - return false - } -} - -func IsScalarComparison(expr *sqlparser.ComparisonExpr) bool { - if expr.Operator != sqlparser.EqualStr { - return false - } - lhs, leftIsVal := expr.Left.(*sqlparser.SQLVal) - rhs, rightIsVal := expr.Right.(*sqlparser.SQLVal) - if !leftIsVal || !rightIsVal { - return false - } - return isScalarSQLVal(lhs) && isScalarSQLVal(rhs) -} diff --git a/internal/stackql/parserutil/parser_util.go b/internal/stackql/parserutil/parser_util.go index a95b2de30..d89dea4db 100644 --- a/internal/stackql/parserutil/parser_util.go +++ b/internal/stackql/parserutil/parser_util.go @@ -16,20 +16,6 @@ const ( FloatBitSize int = 64 ) -func hasAwaitComment(comments sqlparser.Comments) bool { - if comments != nil { - commentDirectives := sqlparser.ExtractCommentDirectives(comments) - if commentDirectives.IsSet("AWAIT") { - return true - } - } - return false -} - -func IsAwait(comments sqlparser.Comments) bool { - return hasAwaitComment(comments) -} - //nolint:gocritic,staticcheck // TODO: clean up this and other tech debt func ExtractLHSTable(sqlFunc *sqlparser.FuncExpr) (*sqlparser.ColName, bool) { if sqlFunc == nil { @@ -49,11 +35,6 @@ func ExtractLHSTable(sqlFunc *sqlparser.FuncExpr) (*sqlparser.ColName, bool) { return nil, false } -// These null "dual" tables are some vitess artifact. -func IsNullTable(node sqlparser.TableExpr) bool { - return isNullTable(node) -} - //nolint:gocritic // TODO: review func isNullTable(node sqlparser.TableExpr) bool { switch node := node.(type) { @@ -68,22 +49,6 @@ func isNullTable(node sqlparser.TableExpr) bool { return false } -//nolint:gocritic // TODO: review -func GetTableNameFromTableExpr(node sqlparser.TableExpr) (sqlparser.TableName, error) { - switch tt := node.(type) { - case *sqlparser.AliasedTableExpr: - tn, ok := tt.Expr.(sqlparser.TableName) - if ok { - return tn, nil - } - } - return sqlparser.TableName{}, fmt.Errorf("table expression too complex") -} - -func NewUnaliasedColumnHandle(name string) ColumnHandle { - return ColumnHandle{Name: name} -} - func ExtractSelectColumnNames(selStmt *sqlparser.Select, formatter sqlparser.NodeFormatter) ([]ColumnHandle, error) { var colNames []ColumnHandle var err error @@ -101,88 +66,6 @@ func ExtractSelectColumnNames(selStmt *sqlparser.Select, formatter sqlparser.Nod return colNames, err } -func ExtractInsertReturningColumnNames( - insertStmt *sqlparser.Insert, - starColumns []string, - formatter sqlparser.NodeFormatter, -) ([]ColumnHandle, error) { - return extractInsertReturningColumnNames( - insertStmt.SelectExprs, - starColumns, - formatter, - ) -} - -func extractInsertReturningColumnNames( - returningExprs sqlparser.SelectExprs, - starColumns []string, - formatter sqlparser.NodeFormatter, -) ([]ColumnHandle, error) { - var colNames []ColumnHandle - var err error - for _, node := range returningExprs { - switch node := node.(type) { - case *sqlparser.AliasedExpr: - cn, cErr := inferColNameFromExpr(node.Expr, formatter, node.As.GetRawVal()) - if cErr != nil { - return nil, cErr - } - colNames = append(colNames, cn) - case *sqlparser.StarExpr: - if len(starColumns) == 0 { - return nil, fmt.Errorf("no star columns provided for insert returning of star") - } - prefix := node.TableName.GetRawVal() - for _, colName := range starColumns { - if prefix != "" { - colName = prefix + "." + colName - } - colNames = append(colNames, ColumnHandle{ - Name: colName, - Alias: colName, - }) - } - default: - err = fmt.Errorf("cannot use SelectExpr of type '%T' as a raw value", node) - return nil, err - } - } - return colNames, err -} - -func ExtractDeleteReturningColumnNames( - deleteStmt *sqlparser.Delete, - starColumns []string, - formatter sqlparser.NodeFormatter, -) ([]ColumnHandle, error) { - return extractInsertReturningColumnNames( - deleteStmt.SelectExprs, - starColumns, - formatter, - ) -} - -func ExtractUpdateReturningColumnNames( - updateStmt *sqlparser.Update, - starColumns []string, - formatter sqlparser.NodeFormatter, -) ([]ColumnHandle, error) { - return extractInsertReturningColumnNames( - updateStmt.SelectExprs, - starColumns, - formatter, - ) -} - -func ExtractInsertColumnNames(insertStmt *sqlparser.Insert) ([]string, error) { - var colNames []string - var err error - for _, node := range insertStmt.Columns { - colNames = append(colNames, node.GetRawVal()) - } - return colNames, err -} - //nolint:gocritic,exhaustive // TODO: review func ExtractAliasedValColumnData(aliasedExpr *sqlparser.AliasedExpr) (map[string]interface{}, error) { alias := aliasedExpr.As.GetRawVal() @@ -422,46 +305,6 @@ func extractUpdateValColumns( return retVal, nonValCols, nil } -//nolint:gocritic // TODO: review -func ExtractWhereColNames(statement *sqlparser.Where) ([]string, error) { - var whereNames []string - var err error - sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { //nolint:errcheck // TODO: review - switch node := node.(type) { - case *sqlparser.ColName: - whereNames = append(whereNames, node.Name.String()) - } - return true, err - }, statement) - return whereNames, err -} - -//nolint:gocritic // TODO: review -func ExtractShowColNames(statement *sqlparser.ShowTablesOpt) ([]string, error) { - var whereNames []string - var err error - if statement == nil || statement.Filter == nil { - return whereNames, err - } - sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { //nolint:errcheck // TODO: review - switch node := node.(type) { - case *sqlparser.ColName: - whereNames = append(whereNames, node.Name.String()) - } - return true, err - }, statement.Filter) - return whereNames, err -} - -func ExtractShowColUsage(statement *sqlparser.ShowTablesOpt) ([]ColumnUsageMetadata, error) { - var colUsageSlice []ColumnUsageMetadata - var err error - if statement == nil || statement.Filter == nil { - return colUsageSlice, err - } - return GetColumnUsageTypes(statement.Filter.Filter) -} - //nolint:gocritic,exhaustive // TODO: review func ExtractSleepDuration(statement *sqlparser.Sleep) (int, error) { var retVal int @@ -475,47 +318,6 @@ func ExtractSleepDuration(statement *sqlparser.Sleep) (int, error) { return retVal, fmt.Errorf("sleep definition inadequate") } -//nolint:gocritic // TODO: review -func GetColumnUsageTypes(statement sqlparser.Expr) ([]ColumnUsageMetadata, error) { - var colMetaSlice []ColumnUsageMetadata - var err error - sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { //nolint:errcheck // TODO: review - switch node := node.(type) { - case *sqlparser.ComparisonExpr: - colMeta := ColumnUsageMetadata{} - switch lhs := node.Left.(type) { - case *sqlparser.ColName: - colMeta.ColName = lhs - } - switch rhs := node.Right.(type) { - case *sqlparser.SQLVal: - colMeta.ColVal = rhs - } - if colMeta.ColName != nil && colMeta.ColVal != nil { - colMetaSlice = append(colMetaSlice, colMeta) - } - } - return true, nil - }, statement) - return colMetaSlice, err -} - -func GetColumnUsageTypesForExec(exec *sqlparser.Exec) ([]ColumnUsageMetadata, error) { - var colMetaSlice []ColumnUsageMetadata - for _, execVarDef := range exec.ExecVarDefs { - colMeta := ColumnUsageMetadata{} - colMeta.ColName = &sqlparser.ColName{Name: execVarDef.ColIdent} - switch rhs := execVarDef.Val.(type) { - case *sqlparser.SQLVal: - colMeta.ColVal = rhs - default: - return nil, fmt.Errorf("EXEC param not supplied as valid SQLVal") - } - colMetaSlice = append(colMetaSlice, colMeta) - } - return colMetaSlice, nil -} - func InferColNameFromExpr(node *sqlparser.AliasedExpr, formatter sqlparser.NodeFormatter) (ColumnHandle, error) { return inferColNameFromExpr(node.Expr, formatter, node.As.GetRawVal()) } @@ -548,10 +350,6 @@ func (s simpleAggSQLCol) getReturnType() sqlparser.ValType { return s.returnType } -func (s simpleAggSQLCol) getName() string { - return s.name -} - func inferAggregatedCol(funcNameLowered string) (aggregatedCol, bool) { switch funcNameLowered { case "count": @@ -800,36 +598,6 @@ func getDecoratedColRendition(baseDecoratedColumn, alias string) string { return baseDecoratedColumn } -//nolint:mnd // TODO: remove this -func CheckSQLParserTypeVsColumn(colUsage ColumnUsageMetadata, verifyCallback func(string, interface{}) bool) error { - switch colUsage.ColVal.Type { - case sqlparser.StrVal: - cn := colUsage.ColName.Name.String() - if !verifyCallback(cn, "") { - return fmt.Errorf("SHOW key = '%s' does NOT match SQL type '%s'", colUsage.ColName.Name.String(), "StrVal") - } - case sqlparser.IntVal: - if !verifyCallback(colUsage.ColName.Name.String(), 11) { - return fmt.Errorf("SHOW key = '%s' does NOT match SQL type '%s'", colUsage.ColName.Name.String(), "IntVal") - } - case sqlparser.FloatVal: - if !verifyCallback(colUsage.ColName.Name.String(), 3.33) { - return fmt.Errorf("SHOW key = '%s' does NOT match SQL type '%s'", colUsage.ColName.Name.String(), "FloatVal") - } - case sqlparser.HexNum: - if !verifyCallback(colUsage.ColName.Name.String(), 0x11) { - return fmt.Errorf("SHOW key = '%s' does NOT match SQL type '%s'", colUsage.ColName.Name.String(), "HexNum") - } - case sqlparser.HexVal: - return fmt.Errorf("SHOW key = '%s' does NOT match SQL type '%s'", colUsage.ColName.Name.String(), "HexVal") - case sqlparser.ValArg: - return fmt.Errorf("SHOW key = '%s' does NOT match SQL type '%s'", colUsage.ColName.Name.String(), "ValArg") - case sqlparser.BitVal: - return fmt.Errorf("SHOW key = '%s' does NOT match SQL type '%s'", colUsage.ColName.Name.String(), "BitVal") - } - return nil -} - func ExtractTableNameFromTableExpr(tableExpr sqlparser.TableExpr) (*sqlparser.TableName, error) { switch table := tableExpr.(type) { case *sqlparser.AliasedTableExpr: @@ -867,27 +635,6 @@ func TableFromSelectNode(sel *sqlparser.Select) (sqlparser.TableName, error) { return tableName, nil } -func IsFromExprSimple(from sqlparser.TableExprs) bool { - for i, node := range from { - if i == 0 { - switch node.(type) { - case *sqlparser.JoinTableExpr, *sqlparser.AliasedTableExpr: - continue - default: - return false - } - } else { - switch node.(type) { - case *sqlparser.TableValuedFuncTableExpr: - continue - default: - return false - } - } - } - return true -} - func IsCreateMaterializedView(stmt sqlparser.Statement) bool { switch st := stmt.(type) { case *sqlparser.DDL: @@ -1038,3 +785,7 @@ func ExtractSelectStatmentFromDDL(stmt sqlparser.Statement) (sqlparser.SelectSta } return nil, false } + +func (s simpleAggSQLCol) getName() string { + return s.name +} diff --git a/internal/stackql/parserutil/rewrite.go b/internal/stackql/parserutil/rewrite.go deleted file mode 100644 index 4157e2cb3..000000000 --- a/internal/stackql/parserutil/rewrite.go +++ /dev/null @@ -1,18 +0,0 @@ -package parserutil - -import ( - "github.com/stackql/stackql-parser/go/vt/sqlparser" -) - -func naiveRewriteComparisonExpr(ex *sqlparser.ComparisonExpr) { - ex.Left = &sqlparser.SQLVal{Type: sqlparser.IntVal, Val: []byte("1")} - ex.Right = &sqlparser.SQLVal{Type: sqlparser.IntVal, Val: []byte("1")} - // ex.Operator = ex.Operator - // ex.Escape = ex.Escape -} - -func NaiveRewriteComparisonExprs(m map[*sqlparser.ComparisonExpr]struct{}) { - for k := range m { - naiveRewriteComparisonExpr(k) - } -} diff --git a/internal/stackql/parserutil/table_parameter_coupling.go b/internal/stackql/parserutil/table_parameter_coupling.go deleted file mode 100644 index d5fb6805f..000000000 --- a/internal/stackql/parserutil/table_parameter_coupling.go +++ /dev/null @@ -1,193 +0,0 @@ -package parserutil - -import ( - "fmt" - - "github.com/stackql/stackql-parser/go/vt/sqlparser" -) - -type ParamSourceType int - -const ( - UnknownParam ParamSourceType = iota - WhereParam - JoinOnParam -) - -type TableParameterCoupling interface { - ColumnKeyedDatastore - getParameterMap() ParameterMap - AbbreviateMap() (map[string]interface{}, error) - Add(ColumnarReference, ParameterMetadata, ParamSourceType) error - DeleteByOrdinal(int) bool - Clone() TableParameterCoupling - GetOnCoupling() TableParameterCoupling - GetNotOnCoupling() TableParameterCoupling - GetAllParameters() []ParameterMapKeyVal - Minus(rhs TableParameterCoupling) TableParameterCoupling - ReconstituteConsumedParams(map[string]interface{}) (TableParameterCoupling, error) -} - -type standardTableParameterCoupling struct { - paramMap ParameterMap - colMappings map[string]ColumnarReference -} - -func NewTableParameterCoupling() TableParameterCoupling { - return &standardTableParameterCoupling{ - paramMap: NewParameterMap(), - colMappings: make(map[string]ColumnarReference), - } -} - -func (tpc *standardTableParameterCoupling) AndStringMap(rhs map[string]interface{}) ColumnKeyedDatastore { - tpc.paramMap.AndStringMap(rhs) - return tpc -} - -func (tpc *standardTableParameterCoupling) DeleteByOrdinal(ord int) bool { - var rv bool - for k, v := range tpc.paramMap.GetMap() { - if v.GetOrdinal() == ord { - rv = tpc.paramMap.Delete(k) - } - } - return rv -} - -func (tpc *standardTableParameterCoupling) DeleteStringMap(rhs map[string]interface{}) ColumnKeyedDatastore { - tpc.paramMap.DeleteStringMap(rhs) - return tpc -} - -func (tpc *standardTableParameterCoupling) Clone() TableParameterCoupling { - colMappings := make(map[string]ColumnarReference) - for k, v := range tpc.colMappings { - colMappings[k] = v - } - return &standardTableParameterCoupling{ - paramMap: tpc.paramMap.Clone(), - colMappings: colMappings, - } -} - -func (tpc *standardTableParameterCoupling) getParameterMap() ParameterMap { - return tpc.paramMap -} - -func (tpc *standardTableParameterCoupling) Minus(rhs TableParameterCoupling) TableParameterCoupling { - difference := tpc.Clone() - rhsParamMap := rhs.getParameterMap() - for _, k := range rhsParamMap.GetAll() { - difference.Delete(k.K) - } - return difference -} - -func (tpc *standardTableParameterCoupling) GetAllParameters() []ParameterMapKeyVal { - return tpc.paramMap.GetAll() -} - -func (tpc *standardTableParameterCoupling) Add( - col ColumnarReference, - val ParameterMetadata, - paramType ParamSourceType, -) error { - colTyped, err := NewColumnarReference(col.Value(), paramType) - if err != nil { - return err - } - err = tpc.paramMap.Set(colTyped, val) - if err != nil { - return err - } - _, ok := tpc.colMappings[col.Name()] - if ok { - return fmt.Errorf("parameter '%s' already present", col.Name()) - } - tpc.colMappings[col.Name()] = col - return nil -} - -func (tpc *standardTableParameterCoupling) Delete(col ColumnarReference) bool { - return tpc.paramMap.Delete(col) -} - -func (tpc *standardTableParameterCoupling) Contains(col ColumnarReference) bool { - return tpc.paramMap.Delete(col) -} - -func (tpc *standardTableParameterCoupling) GetStringified() map[string]interface{} { - return tpc.paramMap.GetAbbreviatedStringified() -} - -func (tpc *standardTableParameterCoupling) DeleteByString(k string) bool { - return tpc.paramMap.DeleteByString(k) -} - -func (tpc *standardTableParameterCoupling) ContainsString(k string) bool { - return tpc.paramMap.ContainsString(k) -} - -func (tpc *standardTableParameterCoupling) AbbreviateMap() (map[string]interface{}, error) { - return tpc.paramMap.GetAbbreviatedStringified(), nil -} - -func (tpc *standardTableParameterCoupling) GetOnCoupling() TableParameterCoupling { - retVal := NewTableParameterCoupling() - m := tpc.paramMap.GetMap() - for k, v := range m { - if k.SourceType() == JoinOnParam { - retVal.Add(k, v, k.SourceType()) //nolint:errcheck // TODO: review - } - } - return retVal -} - -func (tpc *standardTableParameterCoupling) GetNotOnCoupling() TableParameterCoupling { - retVal := NewTableParameterCoupling() - m := tpc.paramMap.GetMap() - for k, v := range m { - if k.SourceType() != JoinOnParam { - retVal.Add(k, v, k.SourceType()) //nolint:errcheck // TODO: review - } - } - return retVal -} - -func (tpc *standardTableParameterCoupling) clone() TableParameterCoupling { - retVal := NewTableParameterCoupling() - m := tpc.paramMap.GetMap() - for k, v := range m { - retVal.Add(k, v, k.SourceType()) //nolint:errcheck // TODO: review - } - return retVal -} - -//nolint:gocritic // TODO: review -func (tpc *standardTableParameterCoupling) ReconstituteConsumedParams( - returnedMap map[string]interface{}, -) (TableParameterCoupling, error) { - retVal := tpc.clone() - for k, v := range returnedMap { - key, ok := tpc.colMappings[k] - if !ok || v == nil { - return nil, fmt.Errorf("no reconstitution mapping for key = '%s'", k) - } - switch kv := key.Value().(type) { - case *sqlparser.ColName: - kv.Metadata = true - } - kv, ok := tpc.paramMap.GetByString(key.String()) - if !ok { - return nil, fmt.Errorf("cannot process consumed params: attempt to locate non existing key") - } - for _, kt := range kv { - ok = retVal.Delete(kt.K) - if !ok { - return nil, fmt.Errorf("cannot process consumed params: attempt to delete non existing key") - } - } - } - return retVal, nil -} diff --git a/internal/stackql/primitivebuilder/sub_tree_builder.go b/internal/stackql/primitivebuilder/sub_tree_builder.go index 5150e404e..bb2bbee32 100644 --- a/internal/stackql/primitivebuilder/sub_tree_builder.go +++ b/internal/stackql/primitivebuilder/sub_tree_builder.go @@ -6,12 +6,6 @@ type SubTreeBuilder struct { children []Builder } -func NewSubTreeBuilder(children []Builder) Builder { - return &SubTreeBuilder{ - children: children, - } -} - func (st *SubTreeBuilder) Build() error { for _, child := range st.children { err := child.Build() diff --git a/internal/stackql/providerconfig/providerconfig.go b/internal/stackql/providerconfig/providerconfig.go deleted file mode 100644 index 3bc16ae1d..000000000 --- a/internal/stackql/providerconfig/providerconfig.go +++ /dev/null @@ -1,17 +0,0 @@ -package providerconfig - -import ( - "os" - - "gopkg.in/yaml.v2" -) - -func ReadProviderConfig(filePath string) (map[string]interface{}, error) { - data, err := os.ReadFile(filePath) - if err != nil { - return nil, err - } - m := make(map[string]interface{}) - err = yaml.Unmarshal(data, &m) - return m, err -} diff --git a/internal/stackql/providerconfig/providerconfig_test.go b/internal/stackql/providerconfig/providerconfig_test.go deleted file mode 100644 index f61d26987..000000000 --- a/internal/stackql/providerconfig/providerconfig_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package providerconfig_test - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stackql/stackql/internal/stackql/providerconfig" -) - -func TestReadProviderConfig_BasicYAML(t *testing.T) { - content := `name: test-provider -version: "1.0" -enabled: true -` - tmpDir := t.TempDir() - configPath := filepath.Join(tmpDir, "config.yaml") - if err := os.WriteFile(configPath, []byte(content), 0644); err != nil { - t.Fatalf("failed to write temp config: %v", err) - } - - result, err := providerconfig.ReadProviderConfig(configPath) - if err != nil { - t.Fatalf("ReadProviderConfig() error = %v", err) - } - if result == nil { - t.Fatal("ReadProviderConfig() returned nil map") - } - if result["name"] != "test-provider" { - t.Errorf("name = %v, want 'test-provider'", result["name"]) - } - if result["version"] != "1.0" { - t.Errorf("version = %v, want '1.0'", result["version"]) - } -} - -func TestReadProviderConfig_NestedYAML(t *testing.T) { - content := `provider: - name: nested - settings: - timeout: 30 - retries: 3 -` - tmpDir := t.TempDir() - configPath := filepath.Join(tmpDir, "nested.yaml") - if err := os.WriteFile(configPath, []byte(content), 0644); err != nil { - t.Fatalf("failed to write temp config: %v", err) - } - - result, err := providerconfig.ReadProviderConfig(configPath) - if err != nil { - t.Fatalf("ReadProviderConfig() error = %v", err) - } - - nested, ok := result["provider"].(map[interface{}]interface{}) - if !ok { - t.Fatalf("provider is not a nested map, got %T", result["provider"]) - } - if nested["name"] != "nested" { - t.Errorf("provider.name = %v, want 'nested'", nested["name"]) - } -} - -func TestReadProviderConfig_EmptyYAML(t *testing.T) { - content := `# just a comment -` - tmpDir := t.TempDir() - configPath := filepath.Join(tmpDir, "empty.yaml") - if err := os.WriteFile(configPath, []byte(content), 0644); err != nil { - t.Fatalf("failed to write temp config: %v", err) - } - - result, err := providerconfig.ReadProviderConfig(configPath) - if err != nil { - t.Fatalf("ReadProviderConfig() error = %v", err) - } - if len(result) != 0 { - t.Errorf("expected empty map, got %d keys", len(result)) - } -} - -func TestReadProviderConfig_FileNotFound(t *testing.T) { - _, err := providerconfig.ReadProviderConfig("/nonexistent/path/config.yaml") - if err == nil { - t.Error("ReadProviderConfig() expected error for non-existent file, got nil") - } -} - -func TestReadProviderConfig_InvalidYAML(t *testing.T) { - content := `invalid: yaml: content: - - broken -` - tmpDir := t.TempDir() - configPath := filepath.Join(tmpDir, "invalid.yaml") - if err := os.WriteFile(configPath, []byte(content), 0644); err != nil { - t.Fatalf("failed to write temp config: %v", err) - } - - _, err := providerconfig.ReadProviderConfig(configPath) - if err == nil { - t.Error("ReadProviderConfig() expected error for invalid YAML, got nil") - } -} - -func TestReadProviderConfig_ListValues(t *testing.T) { - content := `databases: - - postgres - - mysql - - sqlite -` - tmpDir := t.TempDir() - configPath := filepath.Join(tmpDir, "list.yaml") - if err := os.WriteFile(configPath, []byte(content), 0644); err != nil { - t.Fatalf("failed to write temp config: %v", err) - } - - result, err := providerconfig.ReadProviderConfig(configPath) - if err != nil { - t.Fatalf("ReadProviderConfig() error = %v", err) - } - - dbs, ok := result["databases"].([]interface{}) - if !ok { - t.Fatalf("databases is not a list, got %T", result["databases"]) - } - if len(dbs) != 3 { - t.Errorf("databases len = %d, want 3", len(dbs)) - } -} - -func TestReadProviderConfig_SpecialCharacters(t *testing.T) { - content := `query: "SELECT * FROM users WHERE name = 'admin'" -escape: "new\nline\ttab" -` - tmpDir := t.TempDir() - configPath := filepath.Join(tmpDir, "special.yaml") - if err := os.WriteFile(configPath, []byte(content), 0644); err != nil { - t.Fatalf("failed to write temp config: %v", err) - } - - result, err := providerconfig.ReadProviderConfig(configPath) - if err != nil { - t.Fatalf("ReadProviderConfig() error = %v", err) - } - if result["query"] != "SELECT * FROM users WHERE name = 'admin'" { - t.Errorf("query = %v, want SQL string", result["query"]) - } -} diff --git a/internal/stackql/runtimeconfig/auth_ctx.go b/internal/stackql/runtimeconfig/auth_ctx.go index 5ea2b6ce0..31558b8f4 100644 --- a/internal/stackql/runtimeconfig/auth_ctx.go +++ b/internal/stackql/runtimeconfig/auth_ctx.go @@ -358,17 +358,3 @@ func (ac *AuthCtx) GetCredentialsSourceDescriptorString() string { } return fmt.Sprintf("credentialsfilepath:%s", ac.KeyFilePath) } - -func GetAuthCtx(scopes []string, keyFilePath string, keyFileType string) *AuthCtx { - var authType string - if keyFilePath == "" { - authType = AuthInteractiveStr - } else { - authType = inferKeyFileType(keyFileType) - } - return &AuthCtx{AuthConfig: omnisdk.AuthConfig{Scopes: scopes, - Type: authType, - KeyFilePath: keyFilePath, - Active: false}, - } -} diff --git a/internal/stackql/runtimeconfig/context_keys.go b/internal/stackql/runtimeconfig/context_keys.go index 51315ca46..c980090ec 100644 --- a/internal/stackql/runtimeconfig/context_keys.go +++ b/internal/stackql/runtimeconfig/context_keys.go @@ -1,7 +1,5 @@ package dto -import "context" - type ContextKey string const ( @@ -11,13 +9,3 @@ const ( const ( ContextKeyCreationDate ContextKey = "stackql/request/created_date" ) - -func ExtractStackqlRequestContextValue[T any](ctx context.Context, key ContextKey) (T, bool) { - val := ctx.Value(key) - if val == nil { - var zero T - return zero, false - } - typedVal, ok := val.(T) - return typedVal, ok -} diff --git a/internal/stackql/runtimeconfig/dto.go b/internal/stackql/runtimeconfig/dto.go index ad518649f..52e040c41 100644 --- a/internal/stackql/runtimeconfig/dto.go +++ b/internal/stackql/runtimeconfig/dto.go @@ -71,10 +71,3 @@ const ( ViperCfgFileNameKey string = "viperconfigfilename" WorkOfflineKey string = "offline" ) - -func inferKeyFileType(keyFileType string) string { - if keyFileType == "" { - return AuthServiceAccountStr - } - return keyFileType -} diff --git a/internal/stackql/runtimeconfig/marshalled_body.go b/internal/stackql/runtimeconfig/marshalled_body.go deleted file mode 100644 index 249557971..000000000 --- a/internal/stackql/runtimeconfig/marshalled_body.go +++ /dev/null @@ -1,26 +0,0 @@ -package dto - -type MarshalledBody interface { - GetBytes() []byte - GetError() (error, bool) -} - -type standardMarshalledBody struct { - bytes []byte - err error -} - -func NewMarshalledBody(b []byte, e error) MarshalledBody { - return &standardMarshalledBody{ - bytes: b, - err: e, - } -} - -func (mb *standardMarshalledBody) GetBytes() []byte { - return mb.bytes -} - -func (mb *standardMarshalledBody) GetError() (error, bool) { - return mb.err, mb.err != nil -} diff --git a/internal/stackql/session/session.go b/internal/stackql/session/session.go deleted file mode 100644 index 8cff4be96..000000000 --- a/internal/stackql/session/session.go +++ /dev/null @@ -1,6 +0,0 @@ -package session - -type Session interface { - // ExecuteQuery(query string) (interface{}, error) - ExecuteQuery(query string) (interface{}, error) -} diff --git a/internal/stackql/sqlengine/external.go b/internal/stackql/sqlengine/external.go index 62fc33c3d..479cd39a9 100644 --- a/internal/stackql/sqlengine/external.go +++ b/internal/stackql/sqlengine/external.go @@ -3,29 +3,10 @@ package sqlengine import "gopkg.in/yaml.v3" var ( - _ SQLExternalConnection = standardSQLExternalConnection{} - _ SQLExternalTable = standardSQLExternalTable{} - _ SQLExternalColumn = standardSQLExternalColumn{} + _ SQLExternalTable = standardSQLExternalTable{} + _ SQLExternalColumn = standardSQLExternalColumn{} ) -type SQLExternalConnection interface { - GetConnectionName() string - GetTables() map[string]SQLExternalTable -} - -type standardSQLExternalConnection struct { - ConnectionName string `json:"alias" yaml:"alias"` - Tables map[string]SQLExternalTable `json:"tables" yaml:"tables"` -} - -func (c standardSQLExternalConnection) GetConnectionName() string { - return c.ConnectionName -} - -func (c standardSQLExternalConnection) GetTables() map[string]SQLExternalTable { - return c.Tables -} - type SQLExternalTable interface { GetCatalogName() string GetSchemaName() string diff --git a/internal/stackql/sqlstream/sql_map_stream.go b/internal/stackql/sqlstream/sql_map_stream.go deleted file mode 100644 index df745f3cc..000000000 --- a/internal/stackql/sqlstream/sql_map_stream.go +++ /dev/null @@ -1,93 +0,0 @@ -package sqlstream - -import ( - "fmt" - "io" - - "github.com/stackql/stackql/internal/stackql/drm" - "github.com/stackql/stackql/internal/stackql/logging" - "github.com/stackql/stackql/internal/stackql/sqlengine" - "github.com/stackql/stackql/internal/stackql/streaming" - "github.com/stackql/stackql/internal/stackql/tableinsertioncontainer" -) - -type SimpleSQLMapStream struct { - selectCtx drm.PreparedStatementCtx - insertContainer tableinsertioncontainer.TableInsertionContainer - drmCfg drm.Config - sqlEngine sqlengine.SQLEngine - // No buffering just yet; let us revisit soon - staticParams map[string]interface{} -} - -func NewSimpleSQLMapStream( - selectCtx drm.PreparedStatementCtx, - insertContainer tableinsertioncontainer.TableInsertionContainer, - drmCfg drm.Config, - sqlEngine sqlengine.SQLEngine, - staticParams map[string]interface{}, -) streaming.MapStream { - return &SimpleSQLMapStream{ - selectCtx: selectCtx, - insertContainer: insertContainer, - drmCfg: drmCfg, - sqlEngine: sqlEngine, - staticParams: staticParams, - } -} - -func (ss *SimpleSQLMapStream) Write(_ []map[string]interface{}) error { - return nil -} - -func (ss *SimpleSQLMapStream) Read() ([]map[string]interface{}, error) { - var rv []map[string]interface{} - nonControlColumns := ss.selectCtx.GetNonControlColumns() - r, sqlErr := ss.drmCfg.QueryDML( - ss.sqlEngine, - drm.NewPreparedStatementParameterized(ss.selectCtx, nil, true), - ) - if sqlErr != nil { - logging.GetLogger().Infof("sql map stream query error: %v for query: %s", sqlErr, ss.selectCtx.GetQuery()) - return nil, fmt.Errorf("sql map stream query error: %w", sqlErr) - } - if r != nil { - defer r.Close() - } - i := 0 - var keyArr []string - var ifArr []interface{} - for i < len(nonControlColumns) { - x := nonControlColumns[i] - y := ss.drmCfg.GetGolangValue(x.GetType()) - ifArr = append(ifArr, y) - keyArr = append(keyArr, x.GetIdentifier()) - i++ - } - i = 0 - if r != nil { - for r.Next() { - errScan := r.Scan(ifArr...) - if errScan != nil { - return nil, errScan - } - im := make(map[string]interface{}) - for k, v := range ss.staticParams { - im[k] = v - } - for ord, key := range keyArr { - val := ifArr[ord] - ev := ss.drmCfg.ExtractFromGolangValue(val) - im[key] = ev - } - rv = append(rv, im) - logging.GetLogger().Infof( - "sql map stream query returning row '''%v''' for query: '''%s'''", im, ss.selectCtx.GetQuery()) - i++ - } - } - if i == 0 { - logging.GetLogger().Infof("sql map stream query returned no rows for query: '''%s'''", ss.selectCtx.GetQuery()) - } - return rv, io.EOF -} diff --git a/internal/stackql/streaming/map_stream.go b/internal/stackql/streaming/map_stream.go index 2289b55cc..291e8e169 100644 --- a/internal/stackql/streaming/map_stream.go +++ b/internal/stackql/streaming/map_stream.go @@ -32,10 +32,6 @@ type MapStream interface { MapWriter } -func NewstandardMapStream() MapStream { - return &standardMapStream{} -} - func (ss *standardMapStream) Write(input []map[string]interface{}) error { ss.store = append(ss.store, input...) return nil diff --git a/internal/stackql/tableinsertioncontainer/table_insertion_container.go b/internal/stackql/tableinsertioncontainer/table_insertion_container.go deleted file mode 100644 index 963fad097..000000000 --- a/internal/stackql/tableinsertioncontainer/table_insertion_container.go +++ /dev/null @@ -1,66 +0,0 @@ -package tableinsertioncontainer - -import ( - "github.com/stackql/stackql/internal/stackql/internal_data_transfer/internaldto" - "github.com/stackql/stackql/internal/stackql/sqlengine" - "github.com/stackql/stackql/internal/stackql/tablemetadata" - "github.com/stackql/stackql/pkg/txncounter" -) - -var ( - _ TableInsertionContainer = &StandardTableInsertionContainer{} -) - -type TableInsertionContainer interface { - GetTableMetadata() tablemetadata.ExtendedTableMetadata - IsCountersSet() bool - SetTableTxnCounters(string, internaldto.TxnControlCounters) error - GetTableTxnCounters() (string, internaldto.TxnControlCounters) -} - -type StandardTableInsertionContainer struct { - tableName string - tm tablemetadata.ExtendedTableMetadata - tcc internaldto.TxnControlCounters - sqlEngine sqlengine.SQLEngine - isCountersSet bool -} - -func (ic *StandardTableInsertionContainer) GetTableMetadata() tablemetadata.ExtendedTableMetadata { - return ic.tm -} - -func (ic *StandardTableInsertionContainer) SetTableTxnCounters( - tableName string, - tcc internaldto.TxnControlCounters, -) error { - ic.tableName = tableName - ic.tcc.Copy(tcc) - ic.tcc.SetTableName(tableName) - ic.isCountersSet = true - return nil -} - -func (ic *StandardTableInsertionContainer) GetTableTxnCounters() (string, internaldto.TxnControlCounters) { - return ic.tm.GetAlias(), ic.tcc -} - -func (ic *StandardTableInsertionContainer) IsCountersSet() bool { - return ic.isCountersSet -} - -func NewTableInsertionContainer( - tm tablemetadata.ExtendedTableMetadata, - sqlEngine sqlengine.SQLEngine, - txnCtrMgr txncounter.Manager, -) (TableInsertionContainer, error) { - tcc, err := internaldto.NewTxnControlCounters(txnCtrMgr) - if err != nil { - return nil, err - } - return &StandardTableInsertionContainer{ - tm: tm, - tcc: tcc, - sqlEngine: sqlEngine, - }, nil -} diff --git a/internal/stackql/taxonomy/hierarchy.go b/internal/stackql/taxonomy/hierarchy.go index f6fbf91fc..14cacb2d8 100644 --- a/internal/stackql/taxonomy/hierarchy.go +++ b/internal/stackql/taxonomy/hierarchy.go @@ -14,14 +14,6 @@ import ( "github.com/stackql/stackql-parser/go/vt/sqlparser" ) -func GetHeirarchyIDsFromParserNode( - handlerCtx handler.HandlerContext, - node sqlparser.SQLNode, -) (internaldto.HeirarchyIdentifiers, error) { - return GetHIDs( - handlerCtx, node, parserutil.NewParameterMap(), false) -} - // resolveInitialHIDs dispatches on the supplied AST node to derive // hierarchy identifiers, returning either: // - (hIDs, nil, nil) when further view/materialized-view/physical-table @@ -152,10 +144,6 @@ func GetAliasFromStatement(node sqlparser.SQLNode) string { } } -func GetUpdateTargetTableName(node *sqlparser.Update) (string, error) { - return getUpdateTargetTableName(node) -} - func getUpdateTargetTableName(node *sqlparser.Update) (string, error) { if len(node.TableExprs) != 1 { return "", fmt.Errorf("update statement must have exactly one table expression, not %d", len(node.TableExprs)) diff --git a/internal/stackql/typing/relational_column.go b/internal/stackql/typing/relational_column.go index 7af5a56c2..74da2cfbb 100644 --- a/internal/stackql/typing/relational_column.go +++ b/internal/stackql/typing/relational_column.go @@ -12,12 +12,6 @@ var ( _ RelationalColumn = &standardRelationalColumn{} ) -type RelationalColumnByName []RelationalColumn - -func (a RelationalColumnByName) Len() int { return len(a) } -func (a RelationalColumnByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a RelationalColumnByName) Less(i, j int) bool { return a[i].GetName() < a[j].GetName() } - type RelationalColumn interface { CanonicalSelectionString() string DelimitedSelectionString(string) string diff --git a/internal/stackql/util/plan_utility.go b/internal/stackql/util/plan_utility.go index 774784d61..05d14a33b 100644 --- a/internal/stackql/util/plan_utility.go +++ b/internal/stackql/util/plan_utility.go @@ -333,23 +333,6 @@ func DefaultRowSort(rowMap map[string]map[string]interface{}) []string { return []string{} } -func GenerateSimpleErroneousOutput( - err error, - typCfg typing.Config, -) internaldto.ExecutorOutput { - return PrepareResultSet( - internaldto.NewPrepareResultSetDTO( - nil, - nil, - nil, - nil, - err, - nil, - typCfg, - ), - ) -} - //nolint:funlen,gocognit // not overly complex func PrepareResultSet( payload internaldto.PrepareResultSetDTO, diff --git a/internal/stackql/util/utility.go b/internal/stackql/util/utility.go index 9861d6492..6eb93c68e 100644 --- a/internal/stackql/util/utility.go +++ b/internal/stackql/util/utility.go @@ -33,11 +33,3 @@ func MaxMapKey(numbers map[int]interface{}) int { } return maxNumber } - -func TrimSelectItemsKey(selectItemsKey string) string { - splitSet := strings.Split(selectItemsKey, "/") - if len(splitSet) == 0 { - return "" - } - return splitSet[len(splitSet)-1] -} diff --git a/mcp_client/cmd/root.go b/mcp_client/cmd/root.go index 120e5d3a2..872d1001b 100644 --- a/mcp_client/cmd/root.go +++ b/mcp_client/cmd/root.go @@ -31,13 +31,14 @@ var ( //nolint:revive,gochecknoglobals // explicit preferred var ( - BuildMajorVersion string = "" - BuildMinorVersion string = "" - BuildPatchVersion string = "" - BuildCommitSHA string = "" - BuildShortCommitSHA string = "" - BuildDate string = "" - BuildPlatform string = "" + BuildMajorVersion string = "" + BuildMinorVersion string = "" + BuildPatchVersion string = "" + BuildPreReleaseSuffix string = "" + BuildCommitSHA string = "" + BuildShortCommitSHA string = "" + BuildDate string = "" + BuildPlatform string = "" ) // rootCmd represents the base command when called without any subcommands. diff --git a/test/python/stackql_test_tooling/stackql_context.py b/test/python/stackql_test_tooling/stackql_context.py index fbc059f47..394b0368c 100644 --- a/test/python/stackql_test_tooling/stackql_context.py +++ b/test/python/stackql_test_tooling/stackql_context.py @@ -26,6 +26,7 @@ _BUILD_MAJOR_VERSION = os.environ.get('BUILDMAJORVERSION', '1') _BUILD_MINOR_VERSION = os.environ.get('BUILDMINORVERSION', '1') _BUILD_PATCH_VERSION = os.environ.get('BUILDPATCHVERSION', '1') +_BUILD_PRERELEASE_SUFFIX = os.environ.get('BUILDPRERELEASESUFFIX', '') def get_shell_welcome_stdout(env: str) -> str: return '' @@ -906,7 +907,7 @@ def get_registry_mock_url(execution_env :str) -> str: 'BUILDMAJORVERSION': _BUILD_MAJOR_VERSION, 'BUILDMINORVERSION': _BUILD_MINOR_VERSION, 'BUILDPATCHVERSION': _BUILD_PATCH_VERSION, - 'EXPECTED_SEMVER': f"{_BUILD_MAJOR_VERSION}.{_BUILD_MINOR_VERSION}.{_BUILD_PATCH_VERSION}", + 'EXPECTED_SEMVER': f"{_BUILD_MAJOR_VERSION}.{_BUILD_MINOR_VERSION}.{_BUILD_PATCH_VERSION}{_BUILD_PRERELEASE_SUFFIX}", 'DB_INTERNAL_CFG_LAX': DB_INTERNAL_CFG_LAX, 'DB_SETUP_SRC': get_db_setup_src(sql_backend_str), 'DIGITALOCEAN_SECRET_STR': DIGITALOCEAN_SECRET_STR, diff --git a/test/robot/functional/mcp.robot b/test/robot/functional/mcp.robot index bbc6d6dc5..d42946c75 100644 --- a/test/robot/functional/mcp.robot +++ b/test/robot/functional/mcp.robot @@ -451,7 +451,7 @@ MCP HTTP Server Info Includes Version Should Contain ${result.stdout} sql_backend Should Contain ${result.stdout} provider_registry Should Contain ${result.stdout} mode - Should Match Regexp ${result.stdout} \\d+\\.\\d+\\.\\d+ + Should Match Regexp ${result.stdout} \\d+\\.\\d+\\.\\d+%{BUILDPRERELEASESUFFIX=}(?![\\w.-]) Should Be Equal As Integers ${result.rc} 0 PG Server Show Version @@ -469,7 +469,7 @@ PG Server Show Version ... stdout=${CURDIR}${/}tmp${/}PG-Server-Show-Version-psql.txt ... stderr=${CURDIR}${/}tmp${/}PG-Server-Show-Version-psql-stderr.txt Should Contain ${psql_client_result.stdout} version - Should Match Regexp ${psql_client_result.stdout} \\d+\\.\\d+\\.\\d+ + Should Match Regexp ${psql_client_result.stdout} \\d+\\.\\d+\\.\\d+%{BUILDPRERELEASESUFFIX=}(?![\\w.-]) Should Be Equal As Integers ${psql_client_result.rc} 0 PG Server Show Version Extended @@ -490,7 +490,7 @@ PG Server Show Version Extended Should Contain ${psql_client_result.stdout} commit Should Contain ${psql_client_result.stdout} build_date Should Contain ${psql_client_result.stdout} platform - Should Match Regexp ${psql_client_result.stdout} \\d+\\.\\d+\\.\\d+ + Should Match Regexp ${psql_client_result.stdout} \\d+\\.\\d+\\.\\d+%{BUILDPRERELEASESUFFIX=}(?![\\w.-]) Should Be Equal As Integers ${psql_client_result.rc} 0 PG Server Show Contributors @@ -851,7 +851,7 @@ MCP HTTP Server Restricted Tools Allowlist ... stderr=${CURDIR}${/}tmp${/}MCP-Restricted-server-info-stderr.txt Should Be Equal As Integers ${info_result.rc} 0 Should Contain ${info_result.stdout} version - Should Match Regexp ${info_result.stdout} \\d+\\.\\d+\\.\\d+ + Should Match Regexp ${info_result.stdout} \\d+\\.\\d+\\.\\d+%{BUILDPRERELEASESUFFIX=}(?![\\w.-]) ${denied_result}= Run Process ${STACKQL_MCP_CLIENT_EXE} ... exec ... \-\-client\-type\=http diff --git a/test/robot/functional/stackql_from_cmd_line.robot b/test/robot/functional/stackql_from_cmd_line.robot index 930d2f711..cc7532bd3 100644 --- a/test/robot/functional/stackql_from_cmd_line.robot +++ b/test/robot/functional/stackql_from_cmd_line.robot @@ -763,7 +763,7 @@ Show Insert Google BQ Datasets Show Version [Documentation] Verify the SHOW VERSION column header is rendered and that - ... the value matches a generic semver shape. A literal patch + ... the value has the expected build suffix. A literal patch ... check is intentionally avoided because the patch component ... is the CI run number and changes on every build. Should StackQL Exec Contain @@ -771,12 +771,12 @@ Show Version ... version ... stdout=${CURDIR}/tmp/Show-Version.tmp ${captured}= Get File ${CURDIR}/tmp/Show-Version.tmp - Should Match Regexp ${captured} \\d+\\.\\d+\\.\\d+ + Should Match Regexp ${captured} \\|\\s*\\d+\\.\\d+\\.\\d+%{BUILDPRERELEASESUFFIX=}\\s*\\| Show Version Extended [Documentation] Verify the SHOW EXTENDED VERSION column headers are ... rendered and that the version cell matches a generic - ... semver shape (patch component varies per CI run). + ... semver with the expected suffix (patch varies per CI run). Should StackQL Exec Contain ... SHOW EXTENDED VERSION; ... version @@ -794,7 +794,20 @@ Show Version Extended ... platform ... stdout=${CURDIR}/tmp/Show-Version-Extended-Platform.tmp ${captured}= Get File ${CURDIR}/tmp/Show-Version-Extended.tmp - Should Match Regexp ${captured} \\d+\\.\\d+\\.\\d+ + Should Match Regexp ${captured} \\|\\s*\\d+\\.\\d+\\.\\d+%{BUILDPRERELEASESUFFIX=}\\s*\\| + +Reported Version Includes Expected Prerelease Suffix + [Documentation] Check the exact complete version value, rejecting missing or unexpected suffixes. + FOR ${query} IN SHOW VERSION; SHOW EXTENDED VERSION; + Should StackQL Exec Contain JSON output + ... ${query} + ... version + ... stdout=${CURDIR}/tmp/Expected-Prerelease-Version.json + ${captured}= Get File ${CURDIR}/tmp/Expected-Prerelease-Version.json + ${rows}= Evaluate json.loads($captured) modules=json + Length Should Be ${rows} 1 + Should Match Regexp ${rows}[0][version] ^\\d+\\.\\d+\\.\\d+%{BUILDPRERELEASESUFFIX=}$ + END Show Contributors [Documentation] Issue #320: SHOW CONTRIBUTORS renders the embedded